diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/vxlan-interface.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/vxlan-interface.yml index 2718dfbd302..5472307d98b 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/vxlan-interface.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/vxlan-interface.yml @@ -34,10 +34,11 @@ vxlan_interface: - 10.1.1.11 - id: 112 multicast_group: 239.9.1.6 - - id: 113,115-118 - vni: 10113,10115-10118 - id: 113 multicast_group: 239.2.2.2 + vlan_range: + vlans: 113,115-118 + vnis: 10113,10115-10118 vrfs: - name: Tenant_A_OP_Zone diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/vxlan-interface.md b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/vxlan-interface.md index bca28255e7a..e607cd37322 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/vxlan-interface.md +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/vxlan-interface.md @@ -30,11 +30,14 @@ | [        ecn_propagation](## "vxlan_interface.vxlan1.vxlan.qos.ecn_propagation") | Boolean | | | | Enable copying the ECN marking to/from encapsulated packets.
| | [        map_dscp_to_traffic_class_decapsulation](## "vxlan_interface.vxlan1.vxlan.qos.map_dscp_to_traffic_class_decapsulation") | Boolean | | | | | | [      vlans](## "vxlan_interface.vxlan1.vxlan.vlans") | List, items: Dictionary | | | | | - | [        - id](## "vxlan_interface.vxlan1.vxlan.vlans.[].id") | String | Required, Unique | | | VLAN ID or range of VLAN ID.
When set as range, if no. of vni in range(if set) of `vni` does not match with no. of vlans in the range. The inputs of vlans in the range are ignored. | + | [        - id](## "vxlan_interface.vxlan1.vxlan.vlans.[].id") | String | Required, Unique | | | VLAN ID or range of VLAN ID. | | [          vni](## "vxlan_interface.vxlan1.vxlan.vlans.[].vni") | String | | | | VNI or range of VNI. | - | [          multicast_group](## "vxlan_interface.vxlan1.vxlan.vlans.[].multicast_group") | String | | | | IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. | + | [          multicast_group](## "vxlan_interface.vxlan1.vxlan.vlans.[].multicast_group") | String | | | | IP Multicast Group Address. | | [          flood_vteps](## "vxlan_interface.vxlan1.vxlan.vlans.[].flood_vteps") | List, items: String | | | | | | [            - <str>](## "vxlan_interface.vxlan1.vxlan.vlans.[].flood_vteps.[]") | String | | | | Remote VTEP IP Address. | + | [      vlan_range](## "vxlan_interface.vxlan1.vxlan.vlan_range") | Dictionary | | | | Set VNI on range of vlans. | + | [        vlans](## "vxlan_interface.vxlan1.vxlan.vlan_range.vlans") | String | | | | e.g. 100-110 | + | [        vnis](## "vxlan_interface.vxlan1.vxlan.vlan_range.vnis") | String | | | | e.g. 10100-10110. | | [      vrfs](## "vxlan_interface.vxlan1.vxlan.vrfs") | List, items: Dictionary | | | | | | [        - name](## "vxlan_interface.vxlan1.vxlan.vrfs.[].name") | String | Required, Unique | | | VRF Name. | | [          vni](## "vxlan_interface.vxlan1.vxlan.vrfs.[].vni") | Integer | | | | | @@ -65,11 +68,14 @@ | [        ecn_propagation](## "vxlan_interface.Vxlan1.vxlan.qos.ecn_propagation") | Boolean | | | | Enable copying the ECN marking to/from encapsulated packets.
| | [        map_dscp_to_traffic_class_decapsulation](## "vxlan_interface.Vxlan1.vxlan.qos.map_dscp_to_traffic_class_decapsulation") | Boolean | | | | | | [      vlans](## "vxlan_interface.Vxlan1.vxlan.vlans") | List, items: Dictionary | | | | | - | [        - id](## "vxlan_interface.Vxlan1.vxlan.vlans.[].id") | String | Required, Unique | | | VLAN ID or range of VLAN ID.
When set as range, if no. of vni in range(if set) of `vni` does not match with no. of vlans in the range. The inputs of vlans in the range are ignored. | + | [        - id](## "vxlan_interface.Vxlan1.vxlan.vlans.[].id") | String | Required, Unique | | | VLAN ID or range of VLAN ID. | | [          vni](## "vxlan_interface.Vxlan1.vxlan.vlans.[].vni") | String | | | | VNI or range of VNI. | - | [          multicast_group](## "vxlan_interface.Vxlan1.vxlan.vlans.[].multicast_group") | String | | | | IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. | + | [          multicast_group](## "vxlan_interface.Vxlan1.vxlan.vlans.[].multicast_group") | String | | | | IP Multicast Group Address. | | [          flood_vteps](## "vxlan_interface.Vxlan1.vxlan.vlans.[].flood_vteps") | List, items: String | | | | | | [            - <str>](## "vxlan_interface.Vxlan1.vxlan.vlans.[].flood_vteps.[]") | String | | | | Remote VTEP IP Address. | + | [      vlan_range](## "vxlan_interface.Vxlan1.vxlan.vlan_range") | Dictionary | | | | Set VNI on range of vlans. | + | [        vlans](## "vxlan_interface.Vxlan1.vxlan.vlan_range.vlans") | String | | | | e.g. 100-110 | + | [        vnis](## "vxlan_interface.Vxlan1.vxlan.vlan_range.vnis") | String | | | | e.g. 10100-10110. | | [      vrfs](## "vxlan_interface.Vxlan1.vxlan.vrfs") | List, items: Dictionary | | | | | | [        - name](## "vxlan_interface.Vxlan1.vxlan.vrfs.[].name") | String | Required, Unique | | | VRF Name. | | [          vni](## "vxlan_interface.Vxlan1.vxlan.vrfs.[].vni") | Integer | | | | | @@ -120,18 +126,26 @@ vlans: # VLAN ID or range of VLAN ID. - # When set as range, if no. of vni in range(if set) of `vni` does not match with no. of vlans in the range. The inputs of vlans in the range are ignored. - id: # VNI or range of VNI. vni: - # IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. + # IP Multicast Group Address. multicast_group: flood_vteps: # Remote VTEP IP Address. - + + # Set VNI on range of vlans. + vlan_range: + + # e.g. 100-110 + vlans: + + # e.g. 10100-10110. + vnis: vrfs: # VRF Name. @@ -188,18 +202,26 @@ vlans: # VLAN ID or range of VLAN ID. - # When set as range, if no. of vni in range(if set) of `vni` does not match with no. of vlans in the range. The inputs of vlans in the range are ignored. - id: # VNI or range of VNI. vni: - # IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. + # IP Multicast Group Address. multicast_group: flood_vteps: # Remote VTEP IP Address. - + + # Set VNI on range of vlans. + vlan_range: + + # e.g. 100-110 + vlans: + + # e.g. 10100-10110. + vnis: vrfs: # VRF Name. diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/vxlan-interface.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/vxlan-interface.j2 index 254526e7f64..1a3ab2d7059 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/vxlan-interface.j2 +++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/vxlan-interface.j2 @@ -69,33 +69,36 @@ {% elif vxlan_config.vxlan.multicast.headend_replication is arista.avd.defined(false) %} | Multicast headend-replication | Disabled | {% endif %} -{% if vxlan_config.vxlan.vlans is arista.avd.defined %} +{% if vxlan_config.vxlan.vlans is arista.avd.defined or vxlan_config.vxlan.vlan_range is arista.avd.defined %} ##### VLAN to VNI, Flood List and Multicast Group Mappings | VLAN | VNI | Flood List | Multicast Group | | ---- | --- | ---------- | --------------- | {% set all_vlans = {} %} -{% for vxlan_vlan in vxlan_config.vxlan.vlans %} -{% set vlans = vxlan_vlan.id | arista.avd.range_expand %} -{% set vni = vxlan_vlan.vni | arista.avd.range_expand if vxlan_vlan.vni is arista.avd.defined else [] %} -{% for idx in range(vlans | length) %} -{% set vlan = vlans[idx] %} -{% set vni_value = vni[idx] if (vni | length > idx) else '-' %} -{% do all_vlans.setdefault(vlan, {'vlan': vlan}) %} -{% if vni_value != '-' %} -{% do all_vlans[vlan].update({'vni': vni_value}) %} -{% endif %} -{% if vxlan_vlan.multicast_group is arista.avd.defined %} -{% do all_vlans[vlan].update({'multicast_group': vxlan_vlan.multicast_group}) %} -{% endif %} -{% if vxlan_vlan.flood_vteps is arista.avd.defined %} -{% do all_vlans[vlan].update({'flood_vteps': vxlan_vlan.flood_vteps | join('
')}) %} -{% endif %} -{% endfor %} +{% for vlan in vxlan_config.vxlan.vlans %} +{% do all_vlans.setdefault(vlan.id, {}) %} +{% if vlan.vni is arista.avd.defined %} +{% do all_vlans[vlan.id].update({"vni": vlan.vni}) %} +{% endif %} +{% if vlan.multicast_group is arista.avd.defined %} +{% do all_vlans[vlan.id].update({"multicast_group": vlan.multicast_group}) %} +{% endif %} +{% if vlan.flood_vteps is arista.avd.defined %} +{% do all_vlans[vlan.id].update({'flood_list': vlan.flood_vteps | join('
')}) %} +{% endif %} {% endfor %} -{% for vlan in all_vlans.values() | arista.avd.natural_sort("vlan") %} -| {{ vlan.vlan }} | {{ vlan.vni | arista.avd.default('-') }} | {{ vlan.flood_vteps | arista.avd.default('-') }} | {{ vlan.multicast_group | arista.avd.default('-') }} | +{% if vxlan_config.vxlan.vlan_range.vlans is arista.avd.defined and vxlan_config.vxlan.vlan_range.vnis is arista.avd.defined %} +{% set vlans = vxlan_config.vxlan.vlan_range.vlans | arista.avd.range_expand %} +{% for vlan in vlans %} +{% do all_vlans.setdefault(vlan, {}) %} +{% set vnis = vxlan_config.vxlan.vlan_range.vnis | arista.avd.range_expand %} +{% set vni = vnis[vlans.index(vlan)] %} +{% do all_vlans[vlan].update({"vni": vni}) %} +{% endfor %} +{% endif %} +{% for vlan, data in all_vlans.items() | arista.avd.natural_sort %} +| {{ vlan }} | {{ data.vni | arista.avd.default('-') }} | {{ data.flood_list | arista.avd.default('-') }} | {{ data.multicast_group | arista.avd.default('-') }} | {% endfor %} {% endif %} {% if vxlan_config.vxlan.vrfs is arista.avd.defined %} diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/vxlan-interface.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/vxlan-interface.j2 index ea77911e194..12c1287b123 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/vxlan-interface.j2 +++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/vxlan-interface.j2 @@ -32,11 +32,14 @@ interface Vxlan1 {% endif %} {% for vlan in vxlan_config.vxlan.vlans | arista.avd.natural_sort('id') %} {% if vlan.vni is arista.avd.defined %} -{% if vlan.id | arista.avd.range_expand | length == vlan.vni | arista.avd.range_expand | length %} vxlan vlan {{ vlan.id }} vni {{ vlan.vni }} -{% endif %} {% endif %} {% endfor %} +{% if vxlan_config.vxlan.vlan_range is arista.avd.defined %} +{% if vxlan_config.vxlan.vlan_range.vlans is arista.avd.defined and vxlan_config.vxlan.vlan_range.vnis is arista.avd.defined %} + vxlan vlan {{ vxlan_config.vxlan.vlan_range.vlans }} vni {{ vxlan_config.vxlan.vlan_range.vnis }} +{% endif %} +{% endif %} {% for vrf in vxlan_config.vxlan.vrfs | arista.avd.natural_sort('name') %} {% if vrf.vni is arista.avd.defined %} vxlan vrf {{ vrf.name }} vni {{ vrf.vni }} diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py b/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py index 5c858c5420c..4cca2d14e69 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py @@ -66942,15 +66942,11 @@ class FloodVteps(AvdList[str]): "_custom_data": {"type": dict}, } id: str - """ - VLAN ID or range of VLAN ID. - When set as range, if no. of vni in range(if set) of `vni` does not - match with no. of vlans in the range. The inputs of vlans in the range are ignored. - """ + """VLAN ID or range of VLAN ID.""" vni: str | None """VNI or range of VNI.""" multicast_group: str | None - """IP Multicast Group Address. Set this only when `id` is not a range of VLAN id.""" + """IP Multicast Group Address.""" flood_vteps: FloodVteps """Subclass of AvdList with `str` items.""" _custom_data: dict[str, Any] @@ -66973,12 +66969,9 @@ def __init__( Subclass of AvdModel. Args: - id: - VLAN ID or range of VLAN ID. - When set as range, if no. of vni in range(if set) of `vni` does not - match with no. of vlans in the range. The inputs of vlans in the range are ignored. + id: VLAN ID or range of VLAN ID. vni: VNI or range of VNI. - multicast_group: IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. + multicast_group: IP Multicast Group Address. flood_vteps: Subclass of AvdList with `str` items. _custom_data: _custom_data @@ -66991,6 +66984,38 @@ class Vlans(AvdIndexedList[str, VlansItem]): Vlans._item_type = VlansItem + class VlanRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlans": {"type": str}, "vnis": {"type": str}, "_custom_data": {"type": dict}} + vlans: str | None + """e.g. 100-110""" + vnis: str | None + """e.g. 10100-10110.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlans: str | None | UndefinedType = Undefined, + vnis: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanRange. + + + Subclass of AvdModel. + + Args: + vlans: e.g. 100-110 + vnis: e.g. 10100-10110. + _custom_data: _custom_data + + """ + class VrfsItem(AvdModel): """Subclass of AvdModel.""" @@ -67049,6 +67074,7 @@ class FloodVteps(AvdList[str]): "bfd_vtep_evpn": {"type": BfdVtepEvpn}, "qos": {"type": Qos}, "vlans": {"type": Vlans}, + "vlan_range": {"type": VlanRange}, "vrfs": {"type": Vrfs}, "flood_vteps": {"type": FloodVteps}, "flood_vtep_learned_data_plane": {"type": bool}, @@ -67084,6 +67110,12 @@ class FloodVteps(AvdList[str]): """ vlans: Vlans """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`str`).""" + vlan_range: VlanRange + """ + Set VNI on range of vlans. + + Subclass of AvdModel. + """ vrfs: Vrfs """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" flood_vteps: FloodVteps @@ -67106,6 +67138,7 @@ def __init__( bfd_vtep_evpn: BfdVtepEvpn | UndefinedType = Undefined, qos: Qos | UndefinedType = Undefined, vlans: Vlans | UndefinedType = Undefined, + vlan_range: VlanRange | UndefinedType = Undefined, vrfs: Vrfs | UndefinedType = Undefined, flood_vteps: FloodVteps | UndefinedType = Undefined, flood_vtep_learned_data_plane: bool | None | UndefinedType = Undefined, @@ -67138,6 +67171,10 @@ def __init__( Subclass of AvdModel. vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`str`). + vlan_range: + Set VNI on range of vlans. + + Subclass of AvdModel. 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 @@ -67333,15 +67370,11 @@ class FloodVteps(AvdList[str]): "_custom_data": {"type": dict}, } id: str - """ - VLAN ID or range of VLAN ID. - When set as range, if no. of vni in range(if set) of `vni` does not - match with no. of vlans in the range. The inputs of vlans in the range are ignored. - """ + """VLAN ID or range of VLAN ID.""" vni: str | None """VNI or range of VNI.""" multicast_group: str | None - """IP Multicast Group Address. Set this only when `id` is not a range of VLAN id.""" + """IP Multicast Group Address.""" flood_vteps: FloodVteps """Subclass of AvdList with `str` items.""" _custom_data: dict[str, Any] @@ -67364,12 +67397,9 @@ def __init__( Subclass of AvdModel. Args: - id: - VLAN ID or range of VLAN ID. - When set as range, if no. of vni in range(if set) of `vni` does not - match with no. of vlans in the range. The inputs of vlans in the range are ignored. + id: VLAN ID or range of VLAN ID. vni: VNI or range of VNI. - multicast_group: IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. + multicast_group: IP Multicast Group Address. flood_vteps: Subclass of AvdList with `str` items. _custom_data: _custom_data @@ -67382,6 +67412,38 @@ class Vlans(AvdIndexedList[str, VlansItem]): Vlans._item_type = VlansItem + class VlanRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlans": {"type": str}, "vnis": {"type": str}, "_custom_data": {"type": dict}} + vlans: str | None + """e.g. 100-110""" + vnis: str | None + """e.g. 10100-10110.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlans: str | None | UndefinedType = Undefined, + vnis: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanRange. + + + Subclass of AvdModel. + + Args: + vlans: e.g. 100-110 + vnis: e.g. 10100-10110. + _custom_data: _custom_data + + """ + class VrfsItem(AvdModel): """Subclass of AvdModel.""" @@ -67440,6 +67502,7 @@ class FloodVteps(AvdList[str]): "bfd_vtep_evpn": {"type": BfdVtepEvpn}, "qos": {"type": Qos}, "vlans": {"type": Vlans}, + "vlan_range": {"type": VlanRange}, "vrfs": {"type": Vrfs}, "flood_vteps": {"type": FloodVteps}, "flood_vtep_learned_data_plane": {"type": bool}, @@ -67475,6 +67538,12 @@ class FloodVteps(AvdList[str]): """ vlans: Vlans """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`str`).""" + vlan_range: VlanRange + """ + Set VNI on range of vlans. + + Subclass of AvdModel. + """ vrfs: Vrfs """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" flood_vteps: FloodVteps @@ -67497,6 +67566,7 @@ def __init__( bfd_vtep_evpn: BfdVtepEvpn | UndefinedType = Undefined, qos: Qos | UndefinedType = Undefined, vlans: Vlans | UndefinedType = Undefined, + vlan_range: VlanRange | UndefinedType = Undefined, vrfs: Vrfs | UndefinedType = Undefined, flood_vteps: FloodVteps | UndefinedType = Undefined, flood_vtep_learned_data_plane: bool | None | UndefinedType = Undefined, @@ -67529,6 +67599,10 @@ def __init__( Subclass of AvdModel. vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`str`). + vlan_range: + Set VNI on range of vlans. + + Subclass of AvdModel. 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 diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml index 18c4bfa310f..a2a3a58a4b4 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml @@ -22025,11 +22025,7 @@ keys: type: str convert_types: - int - description: 'VLAN ID or range of VLAN ID. - - When set as range, if no. of vni in range(if set) of `vni` - does not match with no. of vlans in the range. The inputs - of vlans in the range are ignored.' + description: VLAN ID or range of VLAN ID. vni: type: str convert_types: @@ -22037,13 +22033,22 @@ keys: description: VNI or range of VNI. multicast_group: type: str - description: IP Multicast Group Address. Set this only when - `id` is not a range of VLAN id. + description: IP Multicast Group Address. flood_vteps: type: list items: type: str description: Remote VTEP IP Address. + vlan_range: + type: dict + description: Set VNI on range of vlans. + keys: + vlans: + type: str + description: e.g. 100-110 + vnis: + type: str + description: e.g. 10100-10110. vrfs: type: list primary_key: name diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/vxlan_interface.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/vxlan_interface.schema.yml index 869d07a5ea1..91fb8833617 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/vxlan_interface.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/vxlan_interface.schema.yml @@ -89,7 +89,6 @@ keys: - int description: |- VLAN ID or range of VLAN ID. - When set as range, if no. of vni in range(if set) of `vni` does not match with no. of vlans in the range. The inputs of vlans in the range are ignored. vni: type: str convert_types: @@ -97,12 +96,22 @@ keys: description: VNI or range of VNI. multicast_group: type: str - description: IP Multicast Group Address. Set this only when `id` is not a range of VLAN id. + description: IP Multicast Group Address. flood_vteps: type: list items: type: str description: Remote VTEP IP Address. + vlan_range: + type: dict + description: Set VNI on range of vlans. + keys: + vlans: + type: str + description: e.g. 100-110 + vnis: + type: str + description: e.g. 10100-10110. vrfs: type: list primary_key: name