Skip to content

PyAVD

PyAVD is a python package providing some of the features from the arista.avd Ansible collection without requiring Ansible. PyAVD leverages the same logic as the Ansible collection, so the generated outputs should be exactly the same based on the same inputs.

PyAVD does not provide any inventory or variable management, so PyAVD cannot replace a full Ansible based solution by itself. PyAVD could serve as an element in larger framework.

Supported features:

  • Validation of inputs based on the eos_designs input schema.
  • Generation of “avd_facts” and “structured config” to be used in other PyAVD functions.
  • Validation of “structured config” based on the eos_cli_config_gen input schema.
  • Generation of device configuration.
  • Generation of device documentation.

Feedback is very welcome. Please use GitHub discussions.

Functions overview

Arista AVD Overview Arista AVD Overview

Known limitations

Warning

Input data and “structured_configs” will be in-place updated by various PyAVD functions. Make sure to deep copy the data first if modifications are not allowed.

Warning

get_device_structured_config(), get_device_config() and get_device_doc() are not thread-safe, so avoid running them for the same device across multiple threads.

Note

  • No support for inline Jinja2 or custom Jinja2 templates.
  • The logic uses the hostname as the unique identifier for each device, so overlapping hostnames will not work.
  • For get_avd_facts(), fabric_name is not used or verified and may differ between devices. All devices in the given inputs will be treated as one fabric.
  • hostname must be set in “structured_config” for each device. hostname will be set correctly when using get_structured_config().

Roadmap

Note

Subject to change. No commitments implied.

  • Add examples
  • Add more tests (current coverage is 85%)
  • Add network state validation similar to eos_validate_state.
  • Add CloudVision tag integrations
  • Make PyAVD the source of AVD logic and use as a dependency for the arista.avd Ansible collection.
  • Explore support for custom Jinja2 templates.

Installation

Install the pyavd Python package:

pip install pyavd

Python dependencies are automatically installed with above command.

Optional requirements

To install Ansible AVD collection additional Python requirements install with extra ansible:

pip install pyavd[ansible]

Reference

validate_inputs(inputs)

Validate input variables according to the eos_designs schema as documented on avd.arista.com.

Where supported by the schema, types will be auto type-converted like from “int” to “str”.

Parameters:

Name Type Description Default
inputs dict

Dictionary with inputs for “eos_designs”.

required

Returns:

Type Description
ValidationResult

Validation result object with any validation errors or deprecation warnings.

Source code in python-avd/pyavd/validate_inputs.py
def validate_inputs(inputs: dict) -> ValidationResult:
    """
    Validate input variables according to the `eos_designs` schema as documented on avd.arista.com.

    Where supported by the schema, types will be auto type-converted like from "int" to "str".

    Args:
        inputs: Dictionary with inputs for "eos_designs".

    Returns:
        Validation result object with any validation errors or deprecation warnings.
    """
    # pylint: disable=import-outside-toplevel
    from .avd_schema_tools import EosDesignsAvdSchemaTools

    # pylint: enable=import-outside-toplevel

    eos_designs_schema_tools = EosDesignsAvdSchemaTools()

    # Inplace conversion of data
    validation_result = eos_designs_schema_tools.convert_data(inputs)

    # Validate input data
    validation_result.merge(eos_designs_schema_tools.validate_data(inputs))
    return validation_result

get_avd_facts(all_inputs)

Build avd_facts using the AVD eos_designs_facts logic.

Variables should be converted and validated according to AVD eos_designs schema first using pyavd.validate_inputs.

Note! No support for inline templating or jinja templates for descriptions or ip addressing

Parameters:

Name Type Description Default
all_inputs dict[str, dict]

A dictionary where keys are hostnames and values are dictionaries of input variables per device.

{
    "<hostname1>": dict,
    "<hostname2>": dict,
    ...
}

required

Returns:

Type Description
dict[str, dict]

Nested dictionary with various internal “facts”. The full dict must be given as argument to pyavd.get_device_structured_config:

{"avd_switch_facts": dict, "avd_overlay_peers": dict, "avd_topology_peers": dict}

Source code in python-avd/pyavd/get_avd_facts.py
def get_avd_facts(all_inputs: dict[str, dict]) -> dict[str, dict]:
    """
    Build avd_facts using the AVD eos_designs_facts logic.

    Variables should be converted and validated according to AVD `eos_designs` schema first using `pyavd.validate_inputs`.

    Note! No support for inline templating or jinja templates for descriptions or ip addressing

    Args:
        all_inputs: A dictionary where keys are hostnames and values are dictionaries of input variables per device.
            ```python
            {
                "<hostname1>": dict,
                "<hostname2>": dict,
                ...
            }
            ```

    Returns:
        Nested dictionary with various internal "facts". The full dict must be given as argument to `pyavd.get_device_structured_config`:
            ```python
            {"avd_switch_facts": dict, "avd_overlay_peers": dict, "avd_topology_peers": dict}
            ```
    """
    avd_switch_facts_instances = _create_avd_switch_facts_instances(all_inputs)
    avd_switch_facts = _render_avd_switch_facts(avd_switch_facts_instances)
    avd_overlay_peers, avd_topology_peers = _render_peer_facts(avd_switch_facts)

    return {
        "avd_switch_facts": avd_switch_facts,
        "avd_overlay_peers": avd_overlay_peers,
        "avd_topology_peers": avd_topology_peers,
    }

get_device_structured_config(hostname, inputs, avd_facts)

Build and return the AVD structured configuration for one device.

Parameters:

Name Type Description Default
hostname str

Hostname of device.

required
inputs dict

Dictionary with inputs for “eos_designs”. Variables should be converted and validated according to AVD eos_designs schema first using pyavd.validate_inputs.

required
avd_facts dict

Dictionary of avd_facts as returned from pyavd.get_avd_facts.

required

Returns:

Type Description
dict

Device Structured Configuration as a dictionary

Source code in python-avd/pyavd/get_device_structured_config.py
def get_device_structured_config(hostname: str, inputs: dict, avd_facts: dict) -> dict:
    """
    Build and return the AVD structured configuration for one device.

    Args:
        hostname: Hostname of device.
        inputs: Dictionary with inputs for "eos_designs".
            Variables should be converted and validated according to AVD `eos_designs` schema first using `pyavd.validate_inputs`.
        avd_facts: Dictionary of avd_facts as returned from `pyavd.get_avd_facts`.

    Returns:
        Device Structured Configuration as a dictionary
    """
    # pylint: disable=import-outside-toplevel
    from ._eos_designs.structured_config import get_structured_config
    from ._errors import AristaAvdError
    from .avd_schema_tools import AvdSchemaTools
    from .constants import EOS_CLI_CONFIG_GEN_SCHEMA_ID, EOS_DESIGNS_SCHEMA_ID

    # pylint: enable=import-outside-toplevel
    #
    # Set 'inventory_hostname' on the input hostvars, to keep compatibility with Ansible focused code.
    # Also map in avd_facts without touching the hostvars
    mapped_hostvars = ChainMap(
        {
            "inventory_hostname": hostname,
            "switch": avd_facts["avd_switch_facts"][hostname]["switch"],
        },
        avd_facts,
        inputs,
    )

    input_schema_tools = AvdSchemaTools(schema_id=EOS_DESIGNS_SCHEMA_ID)
    output_schema_tools = AvdSchemaTools(schema_id=EOS_CLI_CONFIG_GEN_SCHEMA_ID)
    result = {}

    # We do not validate input variables in this stage (done in "validate_inputs")
    structured_config = get_structured_config(
        vars=mapped_hostvars,
        input_schema_tools=input_schema_tools,
        output_schema_tools=output_schema_tools,
        result=result,
        templar=None,
        validate=False,
    )
    if result.get("failed"):
        msg = f"{[str(error) for error in result['errors']]}"
        raise AristaAvdError(msg)

    return structured_config

validate_structured_config(structured_config)

Validate structured config according the eos_cli_config_gen schema as documented on avd.arista.com.

Where supported by the schema, types will be auto type-converted like from “int” to “str”.

Parameters:

Name Type Description Default
structured_config dict

Dictionary with structured configuration.

required

Returns:

Type Description
ValidationResult

Validation result object with any validation errors or deprecation warnings.

Source code in python-avd/pyavd/validate_structured_config.py
def validate_structured_config(structured_config: dict) -> ValidationResult:
    """
    Validate structured config according the `eos_cli_config_gen` schema as documented on avd.arista.com.

    Where supported by the schema, types will be auto type-converted like from "int" to "str".

    Args:
        structured_config: Dictionary with structured configuration.

    Returns:
        Validation result object with any validation errors or deprecation warnings.
    """
    # pylint: disable=import-outside-toplevel
    from .avd_schema_tools import EosCliConfigGenAvdSchemaTools

    # pylint: enable=import-outside-toplevel

    eos_cli_config_gen_schema_tools = EosCliConfigGenAvdSchemaTools()
    # Inplace conversion of data
    validation_result = eos_cli_config_gen_schema_tools.convert_data(structured_config)

    # Validate input data
    validation_result.merge(eos_cli_config_gen_schema_tools.validate_data(structured_config))
    return validation_result

get_device_config(structured_config)

Render and return the device configuration using AVD eos_cli_config_gen templates.

Parameters:

Name Type Description Default
structured_config dict

Dictionary with structured configuration. Variables should be converted and validated according to AVD eos_cli_config_gen schema first using pyavd.validate_structured_config.

required

Returns:

Type Description
str

Device configuration in EOS CLI format.

Source code in python-avd/pyavd/get_device_config.py
def get_device_config(structured_config: dict) -> str:
    """
    Render and return the device configuration using AVD eos_cli_config_gen templates.

    Args:
        structured_config: Dictionary with structured configuration.
            Variables should be converted and validated according to AVD `eos_cli_config_gen` schema first using `pyavd.validate_structured_config`.

    Returns:
        Device configuration in EOS CLI format.
    """
    # pylint: disable=import-outside-toplevel
    from .constants import EOS_CLI_CONFIG_GEN_JINJA2_CONFIG_TEMPLATE, EOS_CLI_CONFIG_GEN_JINJA2_PRECOMPILED_TEMPLATE_PATH
    from .templater import Templar

    # pylint: enable=import-outside-toplevel

    templar = Templar(precompiled_templates_path=EOS_CLI_CONFIG_GEN_JINJA2_PRECOMPILED_TEMPLATE_PATH)
    return templar.render_template_from_file(EOS_CLI_CONFIG_GEN_JINJA2_CONFIG_TEMPLATE, structured_config)

get_device_doc(structured_config, add_md_toc=False)

Render and return the device documentation using AVD eos_cli_config_gen templates.

Parameters:

Name Type Description Default
structured_config dict

Dictionary with structured configuration. Variables should be converted and validated according to AVD eos_cli_config_gen schema first using pyavd.validate_structured_config.

required
add_md_toc bool

Add a table of contents for markdown headings.

False

Returns:

Type Description
str

Device documentation in Markdown format.

Source code in python-avd/pyavd/get_device_doc.py
def get_device_doc(structured_config: dict, add_md_toc: bool = False) -> str:
    """
    Render and return the device documentation using AVD eos_cli_config_gen templates.

    Args:
        structured_config: Dictionary with structured configuration.
            Variables should be converted and validated according to AVD `eos_cli_config_gen` schema first using `pyavd.validate_structured_config`.
        add_md_toc: Add a table of contents for markdown headings.

    Returns:
        Device documentation in Markdown format.
    """
    # pylint: disable=import-outside-toplevel
    from .constants import EOS_CLI_CONFIG_GEN_JINJA2_DOCUMENTAITON_TEMPLATE, EOS_CLI_CONFIG_GEN_JINJA2_PRECOMPILED_TEMPLATE_PATH
    from .j2filters import add_md_toc as filter_add_md_toc
    from .templater import Templar

    # pylint: enable=import-outside-toplevel

    templar = Templar(precompiled_templates_path=EOS_CLI_CONFIG_GEN_JINJA2_PRECOMPILED_TEMPLATE_PATH)
    result: str = templar.render_template_from_file(EOS_CLI_CONFIG_GEN_JINJA2_DOCUMENTAITON_TEMPLATE, structured_config)
    if add_md_toc:
        return filter_add_md_toc(result, skip_lines=3)

    return result

ValidationResult

Object containing result of data validation.

Attributes:

Name Type Description
failed bool

True if data is not valid according to the schema. Otherwise False.

validation_errors list[AvdValidationError]

List of AvdValidationErrors containing schema violations.

deprecation_warnings list[AvdDeprecationWarning]

List of AvdDeprecationWarnings containing warning for deprecated inputs.

Source code in python-avd/pyavd/validation_result.py
class ValidationResult:
    """
    Object containing result of data validation.

    Attributes:
        failed: True if data is not valid according to the schema. Otherwise False.
        validation_errors: List of AvdValidationErrors containing schema violations.
        deprecation_warnings: List of AvdDeprecationWarnings containing warning for deprecated inputs.
    """

    failed: bool
    validation_errors: list[AvdValidationError]
    deprecation_warnings: list[AvdDeprecationWarning]

    def __init__(self, failed: bool, validation_errors: list | None = None, deprecation_warnings: list | None = None) -> None:
        self.failed = failed
        self.validation_errors = validation_errors or []
        self.deprecation_warnings = deprecation_warnings or []

    def merge(self, other: ValidationResult) -> None:
        """Merge another ValidationResult instance into this instance."""
        if not isinstance(other, ValidationResult):
            msg = f"Unable to merge type '{type(other)}' into 'ValidationResult"
            raise TypeError(msg)

        self.failed = self.failed or other.failed
        self.validation_errors.extend(other.validation_errors)
        self.deprecation_warnings.extend(other.deprecation_warnings)

merge(other)

Merge another ValidationResult instance into this instance.

Source code in python-avd/pyavd/validation_result.py
def merge(self, other: ValidationResult) -> None:
    """Merge another ValidationResult instance into this instance."""
    if not isinstance(other, ValidationResult):
        msg = f"Unable to merge type '{type(other)}' into 'ValidationResult"
        raise TypeError(msg)

    self.failed = self.failed or other.failed
    self.validation_errors.extend(other.validation_errors)
    self.deprecation_warnings.extend(other.deprecation_warnings)

AVD eos_designs base module to generate interface descriptions.

AvdInterfaceDescriptions

Bases: AvdFacts

Class used to render Interface Descriptions either from custom Jinja2 templates or using default Python Logic.

Since some templates might contain certain legacy variables (switch_), those are mapped from the switch. model

This class is imported adhoc based on the variable templates.interface_descriptions.python_module so it can be overridden by a custom python class.

Attributes starting with _ are internal and may change at any time.

Other attributes are “stable” and changes follow semver practices: - Existing attributes will not be changed in terms of type and value, but the underlying code for cached_properties may change. - New attributes may be added in minor releases. - The init method may change between minor versions as the data may need to be consumed from other sources. - Breaking changes may happen between major releases or in rare cases for bug fixes.

Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
class AvdInterfaceDescriptions(AvdFacts):
    """
    Class used to render Interface Descriptions either from custom Jinja2 templates or using default Python Logic.

    Since some templates might contain certain legacy variables (switch_*),
    those are mapped from the switch.* model

    This class is imported adhoc based on the variable `templates.interface_descriptions.python_module` so it can
    be overridden by a custom python class.

    Attributes starting with _ are internal and may change at any time.

    Other attributes are "stable" and changes follow semver practices:
    - Existing attributes will not be changed in terms of type and value, but the underlying code for cached_properties may change.
    - New attributes may be added in minor releases.
    - The __init__ method may change between minor versions as the data may need to be consumed from other sources.
    - Breaking changes may happen between major releases or in rare cases for bug fixes.
    """

    def _template(self, template_path: str, **kwargs: Any) -> str:
        template_vars = ChainMap(kwargs, self._hostvars)
        return self.shared_utils.template_var(template_path, template_vars)

    def underlay_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build an underlay Ethernet interface description.

        If a jinja template is configured, use it.

        Available data:
            - link_type
            - description
            - peer
            - peer_interface
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type
            - vrf
            - wan_carrier
            - wan_circuit_id.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_ethernet_interfaces"):
            return self._template(
                template_path,
                link={
                    "type": data.link_type,
                    "peer": data.peer,
                    "peer_interface": data.peer_interface,
                },
            )

        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
        elif data.link_type == "underlay_l2":
            description = self.shared_utils.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])
            return f"{description}_vrf_{data.vrf}" if data.vrf is not None else description

        return AvdStringFormatter().format(
            description,
            **strip_null_from_data(
                {
                    "peer": data.peer,
                    "peer_interface": data.peer_interface,
                    "vrf": data.vrf,
                }
            ),
        )

    def underlay_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build an underlay Port-Channel interface description.

        If a jinja template is configured, use it.

        Available data:
            - peer
            - peer_interface
            - peer_channel_group_id
            - peer_node_group
            - port_channel_id
            - port_channel_description
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_port_channel_interfaces"):
            return self._template(
                template_path,
                link={
                    "peer": data.peer,
                    "channel_group_id": data.port_channel_id,
                    "peer_channel_group_id": data.peer_channel_group_id,
                    "channel_description": data.port_channel_description,
                    "peer_node_group": data.peer_node_group,
                },
            )

        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
        else:
            # This is for L2 port-channels
            description = self.shared_utils.underlay_l2_port_channel_description

        return AvdStringFormatter().format(
            description,
            **strip_null_from_data(
                {
                    "peer": data.peer,
                    "interface": data.interface,
                    "peer_interface": data.peer_interface,
                    "port_channel_id": data.port_channel_id,
                    "peer_port_channel_id": data.peer_channel_group_id,
                    "peer_node_group": data.peer_node_group,
                    "peer_node_group_or_peer": data.peer_node_group or data.peer,
                    "peer_node_group_or_uppercase_peer": data.peer_node_group or str(data.peer or "").upper() or None,
                }
            ),
        )

    def mlag_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build an MLAG Ethernet interface description.

        If a jinja template is configured, use it.
        If not, use the default template as a format string template.

        Available data:
            - interface
            - peer_interface
            - mlag_peer
            - mlag_port_channel_id
            - mlag_peer_port_channel_id
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_ethernet_interfaces"):
            return self._template(
                template_path,
                mlag_interface=data.interface,
                mlag_peer=data.mlag_peer,
            )

        return AvdStringFormatter().format(
            self.shared_utils.mlag_member_description,
            **strip_null_from_data(
                {
                    "mlag_peer": data.mlag_peer,
                    "interface": data.interface,
                    "peer_interface": data.peer_interface,
                    "mlag_port_channel_id": data.mlag_port_channel_id,
                    "mlag_peer_port_channel_id": data.mlag_peer_port_channel_id,
                }
            ),
        )

    def mlag_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build an MLAG Port-Channel interface description.

        If a jinja template is configured, use it.
        If not, use the default template as a format string template.

        Available data:
            - interface
            - peer_interface
            - mlag_peer
            - mlag_port_channel_id
            - mlag_peer_port_channel_id
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_port_channel_interfaces"):
            return self._template(
                template_path,
                mlag_interfaces=data.mlag_interfaces,
                mlag_peer=data.mlag_peer,
                mlag_port_channel_id=data.mlag_port_channel_id,
            )

        return AvdStringFormatter().format(
            self.shared_utils.mlag_port_channel_description,
            **strip_null_from_data(
                {
                    "mlag_peer": data.mlag_peer,
                    "interface": data.interface,
                    "peer_interface": data.peer_interface,
                    "mlag_port_channel_id": data.mlag_port_channel_id,
                    "mlag_peer_port_channel_id": data.mlag_peer_port_channel_id,
                }
            ),
        )

    def mlag_peer_svi(self, data: InterfaceDescriptionData) -> str:
        """
        Build an MLAG Peering SVI description.

        Available data:
            - interface
            - mlag_peer
            - mlag_peer_vlan
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        return AvdStringFormatter().format(
            self.shared_utils.mlag_peer_svi_description,
            **strip_null_from_data(
                {
                    "mlag_peer": data.mlag_peer,
                    "interface": data.interface,
                    "mlag_peer_vlan": data.mlag_peer_vlan,
                }
            ),
        )

    def mlag_peer_l3_svi(self, data: InterfaceDescriptionData) -> str:
        """
        Build an MLAG Peering SVI description.

        Available data:
            - interface
            - mlag_peer
            - mlag_peer_l3_vlan
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        return AvdStringFormatter().format(
            self.shared_utils.mlag_peer_l3_svi_description,
            **strip_null_from_data(
                {
                    "mlag_peer": data.mlag_peer,
                    "interface": data.interface,
                    "mlag_peer_l3_vlan": data.mlag_peer_l3_vlan,
                }
            ),
        )

    def mlag_peer_l3_vrf_svi(self, data: InterfaceDescriptionData) -> str:
        """
        Build an MLAG Peering SVI description.

        Available data:
            - interface
            - vlan
            - vrf
            - mlag_peer
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        return AvdStringFormatter().format(
            self.shared_utils.mlag_peer_l3_vrf_svi_description,
            **strip_null_from_data(
                {
                    "mlag_peer": data.mlag_peer,
                    "interface": data.interface,
                    "vlan": data.vlan,
                    "vrf": data.vrf,
                }
            ),
        )

    def connected_endpoints_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build a connected endpoint Ethernet interface description.

        If a jinja template is configured, use it.
        If not, use the adapter.description as a format string template if set.
        Finally fall back to default templates depending on this being a network_port or not.

        Available data:
            - peer
            - peer_type
            - peer_interface
            - description
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_ethernet_interfaces"):
            return self._template(
                template_path,
                peer=data.peer,
                peer_interface=data.peer_interface,
                adapter_description=data.description,
                peer_type=data.peer_type,
            )

        if data.description:
            description = data.description
        elif data.peer_type == "network_port":
            description = self.shared_utils.default_network_ports_description
        else:
            description = self.shared_utils.default_connected_endpoints_description

        return AvdStringFormatter().format(
            description,
            **strip_null_from_data(
                {
                    "endpoint": data.peer,
                    "endpoint_port": data.peer_interface,
                    "endpoint_type": data.peer_type,
                }
            ),
        )

    def connected_endpoints_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build a connected endpoint Port-channel description.

        If a jinja template is configured, use it.
        If not, use the port_channel.description as a format string template if set.
        Finally fall back to default templates depending on this being a network_port or not.

        Available data:
            - peer
            - peer_interface
            - peer_type
            - description
            - port_channel_id
            - port_channel_description
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type.
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_port_channel_interfaces"):
            return self._template(
                template_path,
                peer=data.peer,
                adapter_port_channel_id=data.port_channel_id,
                adapter_port_channel_description=data.port_channel_description,
                adapter_description=data.description,
            )

        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
        else:
            port_channel_description = self.shared_utils.default_connected_endpoints_port_channel_description

        # Template the adapter description in case it is being referenced in the port_channel_description
        adapter_description = (
            AvdStringFormatter().format(
                data.description,
                **strip_null_from_data(
                    {
                        "endpoint": data.peer,
                        "endpoint_port": data.peer_interface,
                        "endpoint_type": data.peer_type,
                    }
                ),
            )
            if data.description and "adapter_description" in port_channel_description
            else data.description
        )

        return AvdStringFormatter().format(
            port_channel_description,
            **strip_null_from_data(
                {
                    "endpoint": data.peer,
                    "endpoint_port_channel": data.peer_interface,
                    "endpoint_type": data.peer_type,
                    "port_channel_id": data.port_channel_id,
                    "adapter_description": adapter_description,
                    "adapter_description_or_endpoint": adapter_description or data.peer,
                }
            ),
        )

    def router_id_loopback_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build Router ID loopback interface description.

        Available data:
            - description
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - 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"),
        ):
            return self._template(template_path, overlay_loopback_description=data.description, router_id_loopback_description=data.description)

        return data.description

    def vtep_loopback_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build VTEP loopback interface description.

        Available data:
            - description
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type
        """
        if template_path := self.shared_utils.interface_descriptions_templates.get("vtep_loopback_interface"):
            return self._template(template_path, vtep_loopback_description=data.description)

        return data.description

    def wan_ha_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build WAN HA ethernet interface description.

        Available data:
            - interface
            - peer
            - peer_interface
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type
        """
        return f"WAN_HA_{data.peer}_{data.peer_interface}"

    def wan_ha_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
        """
        Build WAN HA port-channel interface description.

        Available data:
            - interface
            - peer
            - peer_interface
            - mpls_overlay_role
            - mpls_lsr
            - overlay_routing_protocol
            - type
        """
        return f"WAN_HA_{data.peer}_{data.peer_interface}"

connected_endpoints_ethernet_interface(data)

Build a connected endpoint Ethernet interface description.

If a jinja template is configured, use it. If not, use the adapter.description as a format string template if set. Finally fall back to default templates depending on this being a network_port or not.

Available data
  • peer
  • peer_type
  • peer_interface
  • description
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def connected_endpoints_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build a connected endpoint Ethernet interface description.

    If a jinja template is configured, use it.
    If not, use the adapter.description as a format string template if set.
    Finally fall back to default templates depending on this being a network_port or not.

    Available data:
        - peer
        - peer_type
        - peer_interface
        - description
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_ethernet_interfaces"):
        return self._template(
            template_path,
            peer=data.peer,
            peer_interface=data.peer_interface,
            adapter_description=data.description,
            peer_type=data.peer_type,
        )

    if data.description:
        description = data.description
    elif data.peer_type == "network_port":
        description = self.shared_utils.default_network_ports_description
    else:
        description = self.shared_utils.default_connected_endpoints_description

    return AvdStringFormatter().format(
        description,
        **strip_null_from_data(
            {
                "endpoint": data.peer,
                "endpoint_port": data.peer_interface,
                "endpoint_type": data.peer_type,
            }
        ),
    )

connected_endpoints_port_channel_interface(data)

Build a connected endpoint Port-channel description.

If a jinja template is configured, use it. If not, use the port_channel.description as a format string template if set. Finally fall back to default templates depending on this being a network_port or not.

Available data
  • peer
  • peer_interface
  • peer_type
  • description
  • port_channel_id
  • port_channel_description
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def connected_endpoints_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build a connected endpoint Port-channel description.

    If a jinja template is configured, use it.
    If not, use the port_channel.description as a format string template if set.
    Finally fall back to default templates depending on this being a network_port or not.

    Available data:
        - peer
        - peer_interface
        - peer_type
        - description
        - port_channel_id
        - port_channel_description
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_port_channel_interfaces"):
        return self._template(
            template_path,
            peer=data.peer,
            adapter_port_channel_id=data.port_channel_id,
            adapter_port_channel_description=data.port_channel_description,
            adapter_description=data.description,
        )

    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
    else:
        port_channel_description = self.shared_utils.default_connected_endpoints_port_channel_description

    # Template the adapter description in case it is being referenced in the port_channel_description
    adapter_description = (
        AvdStringFormatter().format(
            data.description,
            **strip_null_from_data(
                {
                    "endpoint": data.peer,
                    "endpoint_port": data.peer_interface,
                    "endpoint_type": data.peer_type,
                }
            ),
        )
        if data.description and "adapter_description" in port_channel_description
        else data.description
    )

    return AvdStringFormatter().format(
        port_channel_description,
        **strip_null_from_data(
            {
                "endpoint": data.peer,
                "endpoint_port_channel": data.peer_interface,
                "endpoint_type": data.peer_type,
                "port_channel_id": data.port_channel_id,
                "adapter_description": adapter_description,
                "adapter_description_or_endpoint": adapter_description or data.peer,
            }
        ),
    )

mlag_ethernet_interface(data)

Build an MLAG Ethernet interface description.

If a jinja template is configured, use it. If not, use the default template as a format string template.

Available data
  • interface
  • peer_interface
  • mlag_peer
  • mlag_port_channel_id
  • mlag_peer_port_channel_id
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def mlag_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build an MLAG Ethernet interface description.

    If a jinja template is configured, use it.
    If not, use the default template as a format string template.

    Available data:
        - interface
        - peer_interface
        - mlag_peer
        - mlag_port_channel_id
        - mlag_peer_port_channel_id
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_ethernet_interfaces"):
        return self._template(
            template_path,
            mlag_interface=data.interface,
            mlag_peer=data.mlag_peer,
        )

    return AvdStringFormatter().format(
        self.shared_utils.mlag_member_description,
        **strip_null_from_data(
            {
                "mlag_peer": data.mlag_peer,
                "interface": data.interface,
                "peer_interface": data.peer_interface,
                "mlag_port_channel_id": data.mlag_port_channel_id,
                "mlag_peer_port_channel_id": data.mlag_peer_port_channel_id,
            }
        ),
    )

mlag_peer_l3_svi(data)

Build an MLAG Peering SVI description.

Available data
  • interface
  • mlag_peer
  • mlag_peer_l3_vlan
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def mlag_peer_l3_svi(self, data: InterfaceDescriptionData) -> str:
    """
    Build an MLAG Peering SVI description.

    Available data:
        - interface
        - mlag_peer
        - mlag_peer_l3_vlan
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    return AvdStringFormatter().format(
        self.shared_utils.mlag_peer_l3_svi_description,
        **strip_null_from_data(
            {
                "mlag_peer": data.mlag_peer,
                "interface": data.interface,
                "mlag_peer_l3_vlan": data.mlag_peer_l3_vlan,
            }
        ),
    )

mlag_peer_l3_vrf_svi(data)

Build an MLAG Peering SVI description.

Available data
  • interface
  • vlan
  • vrf
  • mlag_peer
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def mlag_peer_l3_vrf_svi(self, data: InterfaceDescriptionData) -> str:
    """
    Build an MLAG Peering SVI description.

    Available data:
        - interface
        - vlan
        - vrf
        - mlag_peer
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    return AvdStringFormatter().format(
        self.shared_utils.mlag_peer_l3_vrf_svi_description,
        **strip_null_from_data(
            {
                "mlag_peer": data.mlag_peer,
                "interface": data.interface,
                "vlan": data.vlan,
                "vrf": data.vrf,
            }
        ),
    )

mlag_peer_svi(data)

Build an MLAG Peering SVI description.

Available data
  • interface
  • mlag_peer
  • mlag_peer_vlan
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def mlag_peer_svi(self, data: InterfaceDescriptionData) -> str:
    """
    Build an MLAG Peering SVI description.

    Available data:
        - interface
        - mlag_peer
        - mlag_peer_vlan
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    return AvdStringFormatter().format(
        self.shared_utils.mlag_peer_svi_description,
        **strip_null_from_data(
            {
                "mlag_peer": data.mlag_peer,
                "interface": data.interface,
                "mlag_peer_vlan": data.mlag_peer_vlan,
            }
        ),
    )

mlag_port_channel_interface(data)

Build an MLAG Port-Channel interface description.

If a jinja template is configured, use it. If not, use the default template as a format string template.

Available data
  • interface
  • peer_interface
  • mlag_peer
  • mlag_port_channel_id
  • mlag_peer_port_channel_id
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def mlag_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build an MLAG Port-Channel interface description.

    If a jinja template is configured, use it.
    If not, use the default template as a format string template.

    Available data:
        - interface
        - peer_interface
        - mlag_peer
        - mlag_port_channel_id
        - mlag_peer_port_channel_id
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_port_channel_interfaces"):
        return self._template(
            template_path,
            mlag_interfaces=data.mlag_interfaces,
            mlag_peer=data.mlag_peer,
            mlag_port_channel_id=data.mlag_port_channel_id,
        )

    return AvdStringFormatter().format(
        self.shared_utils.mlag_port_channel_description,
        **strip_null_from_data(
            {
                "mlag_peer": data.mlag_peer,
                "interface": data.interface,
                "peer_interface": data.peer_interface,
                "mlag_port_channel_id": data.mlag_port_channel_id,
                "mlag_peer_port_channel_id": data.mlag_peer_port_channel_id,
            }
        ),
    )

router_id_loopback_interface(data)

Build Router ID loopback interface description.

Available data
  • description
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def router_id_loopback_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build Router ID loopback interface description.

    Available data:
        - description
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - 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"),
    ):
        return self._template(template_path, overlay_loopback_description=data.description, router_id_loopback_description=data.description)

    return data.description

underlay_ethernet_interface(data)

Build an underlay Ethernet interface description.

If a jinja template is configured, use it.

Available data
  • link_type
  • description
  • peer
  • peer_interface
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type
  • vrf
  • wan_carrier
  • wan_circuit_id.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def underlay_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build an underlay Ethernet interface description.

    If a jinja template is configured, use it.

    Available data:
        - link_type
        - description
        - peer
        - peer_interface
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type
        - vrf
        - wan_carrier
        - wan_circuit_id.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_ethernet_interfaces"):
        return self._template(
            template_path,
            link={
                "type": data.link_type,
                "peer": data.peer,
                "peer_interface": data.peer_interface,
            },
        )

    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
    elif data.link_type == "underlay_l2":
        description = self.shared_utils.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])
        return f"{description}_vrf_{data.vrf}" if data.vrf is not None else description

    return AvdStringFormatter().format(
        description,
        **strip_null_from_data(
            {
                "peer": data.peer,
                "peer_interface": data.peer_interface,
                "vrf": data.vrf,
            }
        ),
    )

underlay_port_channel_interface(data)

Build an underlay Port-Channel interface description.

If a jinja template is configured, use it.

Available data
  • peer
  • peer_interface
  • peer_channel_group_id
  • peer_node_group
  • port_channel_id
  • port_channel_description
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type.
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def underlay_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build an underlay Port-Channel interface description.

    If a jinja template is configured, use it.

    Available data:
        - peer
        - peer_interface
        - peer_channel_group_id
        - peer_node_group
        - port_channel_id
        - port_channel_description
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type.
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_port_channel_interfaces"):
        return self._template(
            template_path,
            link={
                "peer": data.peer,
                "channel_group_id": data.port_channel_id,
                "peer_channel_group_id": data.peer_channel_group_id,
                "channel_description": data.port_channel_description,
                "peer_node_group": data.peer_node_group,
            },
        )

    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
    else:
        # This is for L2 port-channels
        description = self.shared_utils.underlay_l2_port_channel_description

    return AvdStringFormatter().format(
        description,
        **strip_null_from_data(
            {
                "peer": data.peer,
                "interface": data.interface,
                "peer_interface": data.peer_interface,
                "port_channel_id": data.port_channel_id,
                "peer_port_channel_id": data.peer_channel_group_id,
                "peer_node_group": data.peer_node_group,
                "peer_node_group_or_peer": data.peer_node_group or data.peer,
                "peer_node_group_or_uppercase_peer": data.peer_node_group or str(data.peer or "").upper() or None,
            }
        ),
    )

vtep_loopback_interface(data)

Build VTEP loopback interface description.

Available data
  • description
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def vtep_loopback_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build VTEP loopback interface description.

    Available data:
        - description
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type
    """
    if template_path := self.shared_utils.interface_descriptions_templates.get("vtep_loopback_interface"):
        return self._template(template_path, vtep_loopback_description=data.description)

    return data.description

wan_ha_ethernet_interface(data)

Build WAN HA ethernet interface description.

Available data
  • interface
  • peer
  • peer_interface
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def wan_ha_ethernet_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build WAN HA ethernet interface description.

    Available data:
        - interface
        - peer
        - peer_interface
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type
    """
    return f"WAN_HA_{data.peer}_{data.peer_interface}"

wan_ha_port_channel_interface(data)

Build WAN HA port-channel interface description.

Available data
  • interface
  • peer
  • peer_interface
  • mpls_overlay_role
  • mpls_lsr
  • overlay_routing_protocol
  • type
Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
def wan_ha_port_channel_interface(self, data: InterfaceDescriptionData) -> str:
    """
    Build WAN HA port-channel interface description.

    Available data:
        - interface
        - peer
        - peer_interface
        - mpls_overlay_role
        - mpls_lsr
        - overlay_routing_protocol
        - type
    """
    return f"WAN_HA_{data.peer}_{data.peer_interface}"

InterfaceDescriptionData

This class is used as transport of data between AVD code and instances of AvdInterfaceDescriptions class or subclasses hereof.

Attributes starting with _ are internal and may change at any time.

Other attributes are “stable” and changes follow semver practices: - Existing attributes will not be changed in terms of type and value, but the underlying code for cached_properties may change. - New attributes may be added in minor releases. - The init method may change between minor versions as the data may need to be consumed from other sources. - Breaking changes may happen between major releases.

Source code in python-avd/pyavd/api/interface_descriptions/__init__.py
class InterfaceDescriptionData:
    """
    This class is used as transport of data between AVD code and instances of AvdInterfaceDescriptions class or subclasses hereof.

    Attributes starting with _ are internal and may change at any time.

    Other attributes are "stable" and changes follow semver practices:
    - Existing attributes will not be changed in terms of type and value, but the underlying code for cached_properties may change.
    - New attributes may be added in minor releases.
    - The __init__ method may change between minor versions as the data may need to be consumed from other sources.
    - Breaking changes may happen between major releases.
    """

    _shared_utils: SharedUtils
    description: str | None
    """Set description for interface"""
    interface: str | None
    """Local interface"""
    link_type: str | None
    """Type of connection. Like 'underlay_p2p' or 'underlay_l2'"""
    peer: str | None
    """Hostname of peer"""
    peer_interface: str | None
    """Interface of peer"""
    peer_channel_group_id: int | None
    """Port channel ID of peer"""
    peer_node_group: str | None
    """Node group of peer"""
    peer_type: str | None
    """Type of peer"""
    port_channel_id: int | None
    """Port channel ID"""
    port_channel_description: str | None
    """Set description for port-channel"""
    vlan: int | None
    """VLAN ID"""
    vrf: str | None
    """Interface VRF"""
    wan_carrier: str | None
    """The WAN Carrier this interface is connected to"""
    wan_circuit_id: str | None
    """The WAN Circuit ID for this interface."""

    def __init__(
        self,
        shared_utils: SharedUtils,
        description: str | None = None,
        interface: str | None = None,
        link_type: str | None = None,
        peer: str | None = None,
        peer_interface: str | None = None,
        peer_channel_group_id: int | None = None,
        peer_node_group: str | None = None,
        peer_type: str | None = None,
        port_channel_id: int | None = None,
        port_channel_description: str | None = None,
        vlan: int | None = None,
        vrf: str | None = None,
        wan_carrier: str | None = None,
        wan_circuit_id: str | None = None,
    ) -> None:
        self._shared_utils = shared_utils
        self.description = description
        self.interface = interface
        self.link_type = link_type
        self.peer = peer
        self.peer_interface = peer_interface
        self.peer_channel_group_id = peer_channel_group_id
        self.peer_node_group = peer_node_group
        self.peer_type = peer_type
        self.port_channel_id = port_channel_id
        self.port_channel_description = port_channel_description
        self.vlan = vlan
        self.vrf = vrf
        self.wan_carrier = wan_carrier
        self.wan_circuit_id = wan_circuit_id

    @property
    def mpls_overlay_role(self) -> str | None:
        return self._shared_utils.mpls_overlay_role

    @property
    def overlay_routing_protocol(self) -> str:
        return self._shared_utils.overlay_routing_protocol

    @property
    def mlag_interfaces(self) -> list:
        return self._shared_utils.mlag_interfaces

    @property
    def mlag_peer(self) -> str:
        return self._shared_utils.mlag_peer

    @property
    def mlag_port_channel_id(self) -> int:
        return self._shared_utils.mlag_port_channel_id

    @property
    def mlag_peer_port_channel_id(self) -> int:
        return self._shared_utils.mlag_peer_port_channel_id

    @property
    def mlag_peer_vlan(self) -> int:
        return self._shared_utils.mlag_peer_vlan

    @property
    def mlag_peer_l3_vlan(self) -> int | None:
        return self._shared_utils.mlag_peer_l3_vlan

    @property
    def mpls_lsr(self) -> bool:
        return self._shared_utils.mpls_lsr

    @property
    def type(self) -> str:
        return self._shared_utils.type

description: str | None = description instance-attribute

Set description for interface

interface: str | None = interface instance-attribute

Local interface

Type of connection. Like ‘underlay_p2p’ or ‘underlay_l2’

peer: str | None = peer instance-attribute

Hostname of peer

peer_channel_group_id: int | None = peer_channel_group_id instance-attribute

Port channel ID of peer

peer_interface: str | None = peer_interface instance-attribute

Interface of peer

peer_node_group: str | None = peer_node_group instance-attribute

Node group of peer

peer_type: str | None = peer_type instance-attribute

Type of peer

port_channel_description: str | None = port_channel_description instance-attribute

Set description for port-channel

port_channel_id: int | None = port_channel_id instance-attribute

Port channel ID

vlan: int | None = vlan instance-attribute

VLAN ID

vrf: str | None = vrf instance-attribute

Interface VRF

wan_carrier: str | None = wan_carrier instance-attribute

The WAN Carrier this interface is connected to

wan_circuit_id: str | None = wan_circuit_id instance-attribute

The WAN Circuit ID for this interface.