diff --git a/plugins/module_utils/models/manage_fabric/enums.py b/plugins/module_utils/models/manage_fabric/enums.py index 8bb17076..9c382b0f 100644 --- a/plugins/module_utils/models/manage_fabric/enums.py +++ b/plugins/module_utils/models/manage_fabric/enums.py @@ -31,11 +31,15 @@ class FabricTypeEnum(str, Enum): - `VXLAN_IBGP` - VXLAN fabric with iBGP overlay - `VXLAN_EBGP` - VXLAN fabric with eBGP overlay + - `AIML_VXLAN_IBGP` - AI/ML VXLAN fabric with iBGP overlay + - `AIML_VXLAN_EBGP` - AI/ML VXLAN fabric with eBGP overlay """ VXLAN_IBGP = "vxlanIbgp" VXLAN_EBGP = "vxlanEbgp" EXTERNAL_CONNECTIVITY = "externalConnectivity" + AIML_VXLAN_IBGP = "aimlVxlanIbgp" + AIML_VXLAN_EBGP = "aimlVxlanEbgp" class AlertSuspendEnum(str, Enum): diff --git a/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ebgp_vxlan.py b/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ebgp_vxlan.py new file mode 100644 index 00000000..fa8ccf5b --- /dev/null +++ b/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ebgp_vxlan.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import re +from typing import Any, List, Dict, Optional, ClassVar, Literal + +from ansible_collections.cisco.nd.plugins.module_utils.models.base import NDBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.common.pydantic_compat import ( + ConfigDict, + Field, + field_validator, + model_validator, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.enums import ( + AlertSuspendEnum, + FabricTypeEnum, + LicenseTierEnum, + TelemetryCollectionTypeEnum, + TelemetryStreamingProtocolEnum, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ebgp import ( + VxlanEbgpManagementModel, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_common import ( + ExternalStreamingSettingsModel, + LocationModel, + TelemetrySettingsModel, +) + +""" +# Pydantic models for AI eBGP VXLAN fabric management via Nexus Dashboard + +This module provides Pydantic models for creating, updating, and deleting +AI eBGP VXLAN fabrics through the Nexus Dashboard (ND) API. + +The AI eBGP VXLAN fabric type (aimlVxlanEbgp) is structurally identical to +the standard eBGP VXLAN fabric type (vxlanEbgp) — they share the same +management properties. The only difference is the type discriminator value. + +## Models + +- `AimlVxlanEbgpManagementModel` - AI eBGP VXLAN specific management settings +- `FabricAiEbgpVxlanModel` - Complete AI eBGP VXLAN fabric creation model +""" + + +class AimlVxlanEbgpManagementModel(VxlanEbgpManagementModel): + """ + # Summary + + AI eBGP VXLAN fabric management configuration. + + Inherits all properties from VxlanEbgpManagementModel and overrides + the type discriminator to `aimlVxlanEbgp`. + + ## Raises + + - `ValueError` - If BGP ASN, VLAN ranges, or IP ranges are invalid + - `TypeError` - If required string fields are not provided + """ + + type: Literal[FabricTypeEnum.AIML_VXLAN_EBGP] = Field(description="Type of the fabric", default=FabricTypeEnum.AIML_VXLAN_EBGP) + + +class FabricAiEbgpVxlanModel(NDBaseModel): + """ + # Summary + + Complete model for creating a new AI eBGP VXLAN fabric. + + This model combines all necessary components for AI eBGP VXLAN fabric creation + including basic fabric properties, management settings, telemetry, and streaming + configuration. + + ## Raises + + - `ValueError` - If required fields are missing or invalid + - `TypeError` - If field types don't match expected types + """ + + model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True, populate_by_name=True, extra="allow") + + identifiers: ClassVar[Optional[List[str]]] = ["fabric_name"] + identifier_strategy: ClassVar[Optional[Literal["single", "composite", "hierarchical", "singleton"]]] = "single" + + # Basic Fabric Properties + category: Literal["fabric"] = Field(description="Resource category", default="fabric") + fabric_name: str = Field(alias="name", description="Fabric name", min_length=1, max_length=64) + location: Optional[LocationModel] = Field(description="Geographic location of the fabric", default=None) + + # License, Telemetry, and Operations + license_tier: LicenseTierEnum = Field(alias="licenseTier", description="License Tier for fabric.", default=LicenseTierEnum.ESSENTIALS) + alert_suspend: AlertSuspendEnum = Field( + alias="alertSuspend", description="Alert Suspend state configured on the fabric.", default=AlertSuspendEnum.DISABLED + ) + telemetry_collection: bool = Field(alias="telemetryCollection", description="Enable telemetry collection.", default=True) + telemetry_collection_type: TelemetryCollectionTypeEnum = Field( + alias="telemetryCollectionType", description="Telemetry collection method.", default=TelemetryCollectionTypeEnum.IN_BAND + ) + telemetry_streaming_protocol: TelemetryStreamingProtocolEnum = Field( + alias="telemetryStreamingProtocol", description="Telemetry Streaming Protocol.", default=TelemetryStreamingProtocolEnum.IPV4 + ) + telemetry_source_interface: str = Field( + alias="telemetrySourceInterface", + description="Telemetry Source Interface Loopback ID, only valid if Telemetry Collection is set to inBand.", + default="loopback0", + ) + telemetry_source_vrf: str = Field( + alias="telemetrySourceVrf", description="VRF over which telemetry is streamed, valid only if Telemetry Collection is set to inBand.", default="default" + ) + security_domain: str = Field(alias="securityDomain", description="Security Domain associated with the fabric.", default="all") + + # Core Management Configuration + management: Optional[AimlVxlanEbgpManagementModel] = Field(description="AI eBGP VXLAN management configuration", default=None) + + # Optional Advanced Settings + telemetry_settings: Optional[TelemetrySettingsModel] = Field(alias="telemetrySettings", description="Telemetry configuration", default=None) + external_streaming_settings: ExternalStreamingSettingsModel = Field( + alias="externalStreamingSettings", description="External streaming settings", default_factory=ExternalStreamingSettingsModel + ) + + @field_validator("fabric_name") + @classmethod + def validate_fabric_name(cls, value: str) -> str: + """ + # Summary + + Validate fabric name format and characters. + + ## Raises + + - `ValueError` - If name contains invalid characters or format + """ + if not re.match(r"^[a-zA-Z0-9_-]+$", value): + raise ValueError(f"Fabric name can only contain letters, numbers, underscores, and hyphens, got: {value}") + return value + + @model_validator(mode="after") + def validate_fabric_consistency(self) -> "FabricAiEbgpVxlanModel": + """ + # Summary + + Validate consistency between fabric settings and management configuration. + + ## Raises + + - `ValueError` - If fabric settings are inconsistent + """ + # Ensure management type matches model type + if self.management is not None and self.management.type != FabricTypeEnum.AIML_VXLAN_EBGP: + raise ValueError(f"Management type must be {FabricTypeEnum.AIML_VXLAN_EBGP}") + + # Propagate fabric name to management model + if self.management is not None: + self.management.name = self.fabric_name + + # Propagate BGP ASN to site_id if both are set and site_id is empty + if self.management is not None and self.management.site_id == "" and self.management.bgp_asn is not None: + bgp_asn = self.management.bgp_asn + if "." in bgp_asn: + high, low = bgp_asn.split(".") + self.management.site_id = str(int(high) * 65536 + int(low)) + else: + self.management.site_id = bgp_asn + + # Auto-create default telemetry settings if collection is enabled + if self.telemetry_collection and self.telemetry_settings is None: + self.telemetry_settings = TelemetrySettingsModel() + + return self + + def to_diff_dict(self, **kwargs) -> Dict[str, Any]: + """Export for diff comparison, excluding fields that ND overrides for eBGP fabrics.""" + d = super().to_diff_dict(**kwargs) + # ND always returns nxapiHttp=True for eBGP fabrics regardless of the configured value, + # so exclude it from diff comparison to prevent a persistent false-positive diff. + if "management" in d: + d["management"].pop("nxapiHttp", None) + return d + + @classmethod + def get_argument_spec(cls) -> Dict: + return dict( + state={ + "type": "str", + "default": "merged", + "choices": ["merged", "replaced", "deleted", "overridden"], + }, + config={"required": False, "type": "list", "elements": "dict"}, + ) + + +__all__ = [ + "AimlVxlanEbgpManagementModel", + "FabricAiEbgpVxlanModel", +] diff --git a/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ibgp_vxlan.py b/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ibgp_vxlan.py new file mode 100644 index 00000000..0270802d --- /dev/null +++ b/plugins/module_utils/models/manage_fabric/manage_fabric_ai_ibgp_vxlan.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import re +from typing import List, Dict, Optional, ClassVar, Literal + +from ansible_collections.cisco.nd.plugins.module_utils.models.base import NDBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.common.pydantic_compat import ( + ConfigDict, + Field, + field_validator, + model_validator, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.enums import ( + AlertSuspendEnum, + FabricTypeEnum, + LicenseTierEnum, + TelemetryCollectionTypeEnum, + TelemetryStreamingProtocolEnum, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ibgp import ( + VxlanIbgpManagementModel, +) +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_common import ( + ExternalStreamingSettingsModel, + LocationModel, + TelemetrySettingsModel, +) + +""" +# Pydantic models for AI iBGP VXLAN fabric management via Nexus Dashboard + +This module provides Pydantic models for creating, updating, and deleting +AI iBGP VXLAN fabrics through the Nexus Dashboard (ND) API. + +The AI iBGP VXLAN fabric type (aimlVxlanIbgp) is structurally identical to +the standard iBGP VXLAN fabric type (vxlanIbgp) — they share the same +management properties. The only difference is the type discriminator value. + +## Models + +- `AimlVxlanIbgpManagementModel` - AI iBGP VXLAN specific management settings +- `FabricAiIbgpVxlanModel` - Complete AI iBGP VXLAN fabric creation model +""" + + +class AimlVxlanIbgpManagementModel(VxlanIbgpManagementModel): + """ + # Summary + + AI iBGP VXLAN fabric management configuration. + + Inherits all properties from VxlanIbgpManagementModel and overrides + the type discriminator to `aimlVxlanIbgp`. + + ## Raises + + - `ValueError` - If BGP ASN, VLAN ranges, or IP ranges are invalid + - `TypeError` - If required string fields are not provided + """ + + type: Literal[FabricTypeEnum.AIML_VXLAN_IBGP] = Field(description="Type of the fabric", default=FabricTypeEnum.AIML_VXLAN_IBGP) + + +class FabricAiIbgpVxlanModel(NDBaseModel): + """ + # Summary + + Complete model for creating a new AI iBGP VXLAN fabric. + + This model combines all necessary components for AI iBGP VXLAN fabric creation + including basic fabric properties, management settings, telemetry, and streaming + configuration. + + ## Raises + + - `ValueError` - If required fields are missing or invalid + - `TypeError` - If field types don't match expected types + """ + + model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True, populate_by_name=True, extra="allow") + + identifiers: ClassVar[Optional[List[str]]] = ["fabric_name"] + identifier_strategy: ClassVar[Optional[Literal["single", "composite", "hierarchical", "singleton"]]] = "single" + + # Basic Fabric Properties + category: Literal["fabric"] = Field(description="Resource category", default="fabric") + fabric_name: str = Field(alias="name", description="Fabric name", min_length=1, max_length=64) + location: Optional[LocationModel] = Field(description="Geographic location of the fabric", default=None) + + # License, Telemetry, and Operations + license_tier: LicenseTierEnum = Field(alias="licenseTier", description="License Tier for fabric.", default=LicenseTierEnum.ESSENTIALS) + alert_suspend: AlertSuspendEnum = Field( + alias="alertSuspend", description="Alert Suspend state configured on the fabric.", default=AlertSuspendEnum.DISABLED + ) + telemetry_collection: bool = Field(alias="telemetryCollection", description="Enable telemetry collection.", default=True) + telemetry_collection_type: TelemetryCollectionTypeEnum = Field( + alias="telemetryCollectionType", description="Telemetry collection method.", default=TelemetryCollectionTypeEnum.IN_BAND + ) + telemetry_streaming_protocol: TelemetryStreamingProtocolEnum = Field( + alias="telemetryStreamingProtocol", description="Telemetry Streaming Protocol.", default=TelemetryStreamingProtocolEnum.IPV4 + ) + telemetry_source_interface: str = Field( + alias="telemetrySourceInterface", + description="Telemetry Source Interface Loopback ID, only valid if Telemetry Collection is set to inBand.", + default="loopback0", + ) + telemetry_source_vrf: str = Field( + alias="telemetrySourceVrf", description="VRF over which telemetry is streamed, valid only if Telemetry Collection is set to inBand.", default="default" + ) + security_domain: str = Field(alias="securityDomain", description="Security Domain associated with the fabric.", default="all") + + # Core Management Configuration + management: Optional[AimlVxlanIbgpManagementModel] = Field(description="AI iBGP VXLAN management configuration", default=None) + + # Optional Advanced Settings + telemetry_settings: Optional[TelemetrySettingsModel] = Field(alias="telemetrySettings", description="Telemetry configuration", default=None) + external_streaming_settings: ExternalStreamingSettingsModel = Field( + alias="externalStreamingSettings", description="External streaming settings", default_factory=ExternalStreamingSettingsModel + ) + + @field_validator("fabric_name") + @classmethod + def validate_fabric_name(cls, value: str) -> str: + """ + # Summary + + Validate fabric name format and characters. + + ## Raises + + - `ValueError` - If name contains invalid characters or format + """ + if not re.match(r"^[a-zA-Z0-9_-]+$", value): + raise ValueError(f"Fabric name can only contain letters, numbers, underscores, and hyphens, got: {value}") + return value + + @model_validator(mode="after") + def validate_fabric_consistency(self) -> "FabricAiIbgpVxlanModel": + """ + # Summary + + Validate consistency between fabric settings and management configuration. + + ## Raises + + - `ValueError` - If fabric settings are inconsistent + """ + # Ensure management type matches model type + if self.management is not None and self.management.type != FabricTypeEnum.AIML_VXLAN_IBGP: + raise ValueError(f"Management type must be {FabricTypeEnum.AIML_VXLAN_IBGP}") + + # Propagate fabric name to management model + if self.management is not None: + self.management.name = self.fabric_name + + # Propagate BGP ASN to Site ID management model if not set + if self.management is not None and self.management.site_id == "": + bgp_asn = self.management.bgp_asn + if "." in bgp_asn: + high, low = bgp_asn.split(".") + self.management.site_id = str(int(high) * 65536 + int(low)) + else: + self.management.site_id = bgp_asn + + # Validate telemetry consistency + if self.telemetry_collection and self.telemetry_settings is None: + self.telemetry_settings = TelemetrySettingsModel() + + return self + + @classmethod + def get_argument_spec(cls) -> Dict: + return dict( + state={ + "type": "str", + "default": "merged", + "choices": ["merged", "replaced", "deleted", "overridden"], + }, + config={"required": False, "type": "list", "elements": "dict"}, + ) + + +__all__ = [ + "AimlVxlanIbgpManagementModel", + "FabricAiIbgpVxlanModel", +] diff --git a/plugins/module_utils/orchestrators/manage_fabric_ai_ebgp_vxlan.py b/plugins/module_utils/orchestrators/manage_fabric_ai_ebgp_vxlan.py new file mode 100644 index 00000000..6b5c2f30 --- /dev/null +++ b/plugins/module_utils/orchestrators/manage_fabric_ai_ebgp_vxlan.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from typing import Type +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.base import NDBaseOrchestrator +from ansible_collections.cisco.nd.plugins.module_utils.models.base import NDBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ai_ebgp_vxlan import FabricAiEbgpVxlanModel +from ansible_collections.cisco.nd.plugins.module_utils.endpoints.base import NDEndpointBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.types import ResponseType +from ansible_collections.cisco.nd.plugins.module_utils.endpoints.v1.manage.manage_fabrics import ( + EpManageFabricsGet, + EpManageFabricsListGet, + EpManageFabricsPost, + EpManageFabricsPut, + EpManageFabricsDelete, +) + + +class ManageAiEbgpVxlanFabricOrchestrator(NDBaseOrchestrator): + model_class: Type[NDBaseModel] = FabricAiEbgpVxlanModel + + create_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsPost + update_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsPut + delete_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsDelete + query_one_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsGet + query_all_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsListGet + + def query_all(self) -> ResponseType: + """ + Custom query_all action to extract 'fabrics' from response, + filtered to only aimlVxlanEbgp fabric types. + """ + try: + api_endpoint = self.query_all_endpoint() + result = self.sender.query_obj(api_endpoint.path) + fabrics = result.get("fabrics", []) or [] + return [f for f in fabrics if f.get("management", {}).get("type") == "aimlVxlanEbgp"] + except Exception as e: + raise Exception(f"Query all failed: {e}") from e diff --git a/plugins/module_utils/orchestrators/manage_fabric_ai_ibgp_vxlan.py b/plugins/module_utils/orchestrators/manage_fabric_ai_ibgp_vxlan.py new file mode 100644 index 00000000..7530d7cf --- /dev/null +++ b/plugins/module_utils/orchestrators/manage_fabric_ai_ibgp_vxlan.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from typing import Type +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.base import NDBaseOrchestrator +from ansible_collections.cisco.nd.plugins.module_utils.models.base import NDBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ai_ibgp_vxlan import FabricAiIbgpVxlanModel +from ansible_collections.cisco.nd.plugins.module_utils.endpoints.base import NDEndpointBaseModel +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.types import ResponseType +from ansible_collections.cisco.nd.plugins.module_utils.endpoints.v1.manage.manage_fabrics import ( + EpManageFabricsGet, + EpManageFabricsListGet, + EpManageFabricsPost, + EpManageFabricsPut, + EpManageFabricsDelete, +) + + +class ManageAiIbgpVxlanFabricOrchestrator(NDBaseOrchestrator): + model_class: Type[NDBaseModel] = FabricAiIbgpVxlanModel + + create_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsPost + update_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsPut + delete_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsDelete + query_one_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsGet + query_all_endpoint: Type[NDEndpointBaseModel] = EpManageFabricsListGet + + def query_all(self) -> ResponseType: + """ + Custom query_all action to extract 'fabrics' from response, + filtered to only aimlVxlanIbgp fabric types. + """ + try: + api_endpoint = self.query_all_endpoint() + result = self.sender.query_obj(api_endpoint.path) + fabrics = result.get("fabrics", []) or [] + return [f for f in fabrics if f.get("management", {}).get("type") == "aimlVxlanIbgp"] + except Exception as e: + raise Exception(f"Query all failed: {e}") from e diff --git a/plugins/modules/nd_manage_fabric_ai_ebgp_vxlan.py b/plugins/modules/nd_manage_fabric_ai_ebgp_vxlan.py new file mode 100644 index 00000000..4dbe745d --- /dev/null +++ b/plugins/modules/nd_manage_fabric_ai_ebgp_vxlan.py @@ -0,0 +1,1697 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: nd_manage_fabric_ai_ebgp_vxlan +version_added: "2.0.0" +short_description: Manage AI/ML eBGP VXLAN fabrics on Cisco Nexus Dashboard +description: +- Manage AI/ML eBGP VXLAN fabrics on Cisco Nexus Dashboard (ND). +- It supports creating, updating, replacing, and deleting AI/ML eBGP VXLAN fabrics. +- AI/ML eBGP VXLAN fabrics are optimized for AI and machine learning workloads using eBGP underlay with VXLAN overlay. +- The AI/ML eBGP VXLAN fabric type (C(aimlVxlanEbgp)) shares the same management properties as the standard eBGP VXLAN + fabric type (C(vxlanEbgp)), but is specifically designated for AI/ML workloads. +author: +- Matt Tarkington (@mtarking) +options: + config: + description: + - The list of AI/ML eBGP VXLAN fabrics to configure. + type: list + elements: dict + suboptions: + fabric_name: + description: + - The name of the fabric. + - Only letters, numbers, underscores, and hyphens are allowed. + - The O(config.fabric_name) must be defined when creating, updating or deleting a fabric. + type: str + required: true + category: + description: + - The resource category. + type: str + default: fabric + location: + description: + - The geographic location of the fabric. + type: dict + suboptions: + latitude: + description: + - Latitude coordinate of the fabric location (-90 to 90). + type: float + required: true + longitude: + description: + - Longitude coordinate of the fabric location (-180 to 180). + type: float + required: true + license_tier: + description: + - The License Tier for fabric. + type: str + default: essentials + choices: [ essentials, advantage, premier ] + alert_suspend: + description: + - The Alert Suspend state configured on the fabric. + type: str + default: disabled + choices: [ enabled, disabled ] + telemetry_collection: + description: + - Enable telemetry collection. + type: bool + default: true + telemetry_collection_type: + description: + - The telemetry collection method. + type: str + default: inBand + choices: [ inBand, outOfBand ] + telemetry_streaming_protocol: + description: + - The Telemetry Streaming Protocol. + type: str + default: ipv4 + choices: [ ipv4, ipv6 ] + telemetry_source_interface: + description: + - Telemetry Source Interface Loopback ID, only valid if Telemetry Collection is set to inBand. + type: str + default: loopback0 + telemetry_source_vrf: + description: + - VRF over which telemetry is streamed, valid only if Telemetry Collection is set to inBand. + type: str + default: default + security_domain: + description: + - The Security Domain associated with the fabric. + type: str + default: all + management: + description: + - The AI/ML eBGP VXLAN management configuration for the fabric. + - Properties are grouped by template section for readability in the module documentation source. + type: dict + suboptions: + # General + type: + description: + - The fabric management type. Must be C(aimlVxlanEbgp) for AI/ML eBGP VXLAN fabrics. + type: str + default: aimlVxlanEbgp + choices: [ aimlVxlanEbgp ] + bgp_asn: + description: + - The BGP Autonomous System Number for the fabric. + - Must be a numeric value between 1 and 4294967295, or dotted notation (1-65535.0-65535). + - Optional when O(config.management.bgp_asn_auto_allocation) is C(true). + type: str + bgp_asn_auto_allocation: + description: + - Enable automatic BGP ASN allocation from the O(config.management.bgp_asn_range) pool. + type: bool + default: true + bgp_asn_range: + description: + - The BGP ASN range to use for automatic ASN allocation (e.g. C(65000-65535)). + - Required when O(config.management.bgp_asn_auto_allocation) is C(true). + type: str + bgp_as_mode: + description: + - The BGP AS mode for the fabric. + - C(multiAS) assigns a unique AS number per leaf/border/border gateway (borders and border gateways may share ASN). + - C(sameTierAS) assigns the same AS number within a tier (leafs share one ASN, borders/border gateways share one ASN). + type: str + default: multiAS + choices: [ multiAS, sameTierAS ] + bgp_allow_as_in_num: + description: + - The number of occurrences of the local AS number allowed in the BGP AS-path. + type: int + default: 1 + bgp_max_path: + description: + - The maximum number of BGP equal-cost paths. + type: int + default: 4 + bgp_underlay_failure_protect: + description: + - Enable BGP underlay failure protection. + type: bool + default: false + auto_configure_ebgp_evpn_peering: + description: + - Automatically configure eBGP EVPN overlay peering between leaf and spine switches. + type: bool + default: true + allow_leaf_same_as: + description: + - Allow leaf switches to have the same BGP ASN even when AS mode is Multi-AS. + type: bool + default: false + assign_ipv4_to_loopback0: + description: + - In an IPv6 routed fabric or VXLAN EVPN fabric with IPv6 underlay, assign IPv4 address + used for BGP Router ID to the routing loopback interface. + type: bool + default: true + evpn: + description: + - Enable BGP EVPN as the control plane and VXLAN as the data plane for this fabric. + type: bool + default: true + route_map_tag: + description: + - Tag for Route Map FABRIC-RMAP-REDIST-SUBNET. (Min 0, Max 4294967295). + type: int + default: 12345 + disable_route_map_tag: + description: + - Disable match tag for Route Map FABRIC-RMAP-REDIST-SUBNET. + type: bool + default: false + leaf_bgp_as: + description: + - The BGP AS number for leaf switches. + - Autonomous system number 1-4294967295 or dotted notation 1-65535.0-65535. + type: str + border_bgp_as: + description: + - The BGP AS number for border switches. + - Autonomous system number 1-4294967295 or dotted notation 1-65535.0-65535. + type: str + super_spine_bgp_as: + description: + - The BGP AS number for super-spine switches. + - Autonomous system number 1-4294967295 or dotted notation 1-65535.0-65535. + type: str + site_id: + description: + - The site identifier for EVPN Multi-Site support. + - Defaults to the value of O(config.management.bgp_asn) if not provided. + type: str + default: "" + bgp_loopback_id: + description: + - The underlay routing loopback interface ID (0-1023). + type: int + default: 0 + bgp_loopback_ip_range: + description: + - Typically Loopback0 IP address range. + type: str + default: "10.2.0.0/22" + bgp_loopback_ipv6_range: + description: + - Typically Loopback0 IPv6 address range. + type: str + default: "fd00::a02:0/119" + nve_loopback_id: + description: + - The underlay VTEP loopback ID associated with the NVE interface (0-1023). + type: int + default: 1 + nve_loopback_ip_range: + description: + - Typically Loopback1 IP address range. + type: str + default: "10.3.0.0/22" + nve_loopback_ipv6_range: + description: + - Typically Loopback1 and Anycast Loopback IPv6 address range. + type: str + default: "fd00::a03:0/118" + anycast_loopback_id: + description: + - Underlay anycast loopback ID. Used for vPC peering in VXLANv6 fabrics. + type: int + default: 10 + anycast_rendezvous_point_ip_range: + description: + - Anycast or Phantom RP IP address range. + type: str + default: "10.254.254.0/24" + ipv6_anycast_rendezvous_point_ip_range: + description: + - Anycast RP IPv6 address range. + type: str + default: "fd00::254:254:0/118" + intra_fabric_subnet_range: + description: + - Address range to assign numbered and peer link SVI IPs. + type: str + default: "10.4.0.0/16" + l2_vni_range: + description: + - Overlay network identifier range (minimum 1, maximum 16777214). + type: str + default: "30000-49000" + l3_vni_range: + description: + - Overlay VRF identifier range (minimum 1, maximum 16777214). + type: str + default: "50000-59000" + network_vlan_range: + description: + - Per switch overlay network VLAN range (minimum 2, maximum 4094). + type: str + default: "2300-2999" + vrf_vlan_range: + description: + - Per switch overlay VRF VLAN range (minimum 2, maximum 4094). + type: str + default: "2000-2299" + overlay_mode: + description: + - Overlay mode. VRF/Network configuration using config-profile or CLI. + type: str + default: cli + choices: [ cli, config-profile ] + replication_mode: + description: + - Replication mode for BUM traffic. + type: str + default: multicast + choices: [ multicast, ingress ] + multicast_group_subnet: + description: + - Multicast pool prefix between 8 to 30. A multicast group IPv4 from this pool + is used for BUM traffic for each overlay network. + type: str + default: "239.1.1.0/25" + auto_generate_multicast_group_address: + description: + - Generate a new multicast group address from the multicast pool using a round-robin approach. + type: bool + default: false + underlay_multicast_group_address_limit: + description: + - The maximum supported value is 128 for NX-OS version 10.2(1) or earlier + and 512 for versions above 10.2(1). + type: int + default: 128 + choices: [ 128, 512 ] + tenant_routed_multicast: + description: + - Enable overlay IPv4 multicast support in VXLAN fabrics. + type: bool + default: false + tenant_routed_multicast_ipv6: + description: + - Enable overlay IPv6 multicast support in VXLAN fabrics. + type: bool + default: false + first_hop_redundancy_protocol: + description: + - First hop redundancy protocol, HSRP or VRRP. + type: str + default: hsrp + choices: [ hsrp, vrrp ] + rendezvous_point_count: + description: + - Number of spines acting as Rendezvous-Points (RPs). + type: int + default: 2 + choices: [ 2, 4 ] + rendezvous_point_loopback_id: + description: + - The rendezvous point loopback interface ID. + type: int + default: 254 + rendezvous_point_mode: + description: + - Multicast rendezvous point mode. For IPv6 underlay, use C(asm) only. + type: str + default: asm + choices: [ asm, bidir ] + phantom_rendezvous_point_loopback_id1: + description: + - Underlay phantom rendezvous point loopback primary ID for PIM Bi-dir deployments. + type: int + default: 2 + phantom_rendezvous_point_loopback_id2: + description: + - Underlay phantom rendezvous point loopback secondary ID for PIM Bi-dir deployments. + type: int + default: 3 + phantom_rendezvous_point_loopback_id3: + description: + - Underlay phantom rendezvous point loopback tertiary ID for PIM Bi-dir deployments. + type: int + default: 4 + phantom_rendezvous_point_loopback_id4: + description: + - Underlay phantom rendezvous point loopback quaternary ID for PIM Bi-dir deployments. + type: int + default: 5 + l3vni_multicast_group: + description: + - Default underlay multicast group IPv4 address assigned for every overlay VRF. + type: str + default: "239.1.1.0" + l3_vni_ipv6_multicast_group: + description: + - Default underlay multicast group IPv6 address assigned for every overlay VRF. + type: str + default: "ff1e::" + ipv6_multicast_group_subnet: + description: + - IPv6 multicast address with prefix 112 to 128. + type: str + default: "ff1e::/121" + mvpn_vrf_route_import_id: + description: + - Enable MVPN VRI ID generation for tenant routed multicast with IPv4 underlay. + type: bool + default: true + mvpn_vrf_route_import_id_range: + description: + - MVPN VRI ID range (minimum 1, maximum 65535) for vPC, applicable when TRM is enabled + with IPv6 underlay, or O(config.management.mvpn_vrf_route_import_id) is enabled with IPv4 underlay. + type: str + vrf_route_import_id_reallocation: + description: + - One time VRI ID re-allocation based on MVPN VRI ID Range. + type: bool + default: false + target_subnet_mask: + description: + - Mask for underlay subnet IP range (24-31). + type: int + default: 30 + anycast_gateway_mac: + description: + - Shared anycast gateway MAC address for all VTEPs in xxxx.xxxx.xxxx format. + type: str + default: 2020.0000.00aa + fabric_mtu: + description: + - Intra fabric interface MTU. Must be an even number (1500-9216). + type: int + default: 9216 + l2_host_interface_mtu: + description: + - Layer 2 host interface MTU. Must be an even number (1500-9216). + type: int + default: 9216 + l3_vni_no_vlan_default_option: + description: + - L3 VNI configuration without VLAN configuration. This value is propagated on VRF + creation as the default value of Enable L3VNI w/o VLAN in VRF. + type: bool + default: false + underlay_ipv6: + description: + - Enable IPv6 underlay. If not enabled, IPv4 underlay is used. + type: bool + default: false + static_underlay_ip_allocation: + description: + - Disable dynamic underlay IP address allocation. + type: bool + default: false + anycast_border_gateway_advertise_physical_ip: + description: + - Advertise Anycast Border Gateway PIP as VTEP. + Effective on MSD fabric Recalculate Config. + type: bool + default: false + sub_interface_dot1q_range: + description: + - Per aggregation dot1q range for VRF-Lite connectivity (minimum 2, maximum 4093). + type: str + default: "2-511" + vrf_lite_auto_config: + description: + - VRF Lite Inter-Fabric Connection Deployment Options. + - If C(back2BackAndToExternal) is selected, VRF Lite IFCs are auto created between + border devices of two Easy Fabrics, and between border devices in Easy Fabric and + edge routers in External Fabric. + type: str + default: manual + choices: [ manual, back2BackAndToExternal ] + vrf_lite_subnet_range: + description: + - Address range to assign P2P interfabric connections. + type: str + default: "10.33.0.0/16" + vrf_lite_subnet_target_mask: + description: + - VRF Lite subnet mask. + type: int + default: 30 + auto_unique_vrf_lite_ip_prefix: + description: + - When enabled, IP prefix allocated to the VRF LITE IFC is not reused on VRF extension + over VRF LITE IFC. Instead, a unique IP subnet is allocated for each VRF extension. + type: bool + default: false + vpc_domain_id_range: + description: + - vPC domain ID range (minimum 1, maximum 1000) to use for new pairings. + type: str + default: "1-1000" + vpc_peer_link_vlan: + description: + - VLAN range (minimum 2, maximum 4094) for vPC Peer Link SVI. + type: str + default: "3600" + vpc_peer_link_enable_native_vlan: + description: + - Enable vPC peer link for native VLAN. + type: bool + default: false + vpc_peer_keep_alive_option: + description: + - Use vPC peer keep alive with loopback or management. + type: str + default: management + choices: [ loopback, management ] + vpc_auto_recovery_timer: + description: + - vPC auto recovery timer in seconds (240-3600). + type: int + default: 360 + vpc_delay_restore_timer: + description: + - vPC delay restore timer in seconds (1-3600). + type: int + default: 150 + vpc_peer_link_port_channel_id: + description: + - vPC peer link port channel ID (minimum 1, maximum 4096). + type: str + default: "500" + vpc_ipv6_neighbor_discovery_sync: + description: + - Enable IPv6 ND synchronization between vPC peers. + type: bool + default: true + vpc_layer3_peer_router: + description: + - Enable layer-3 peer-router on all leaf switches. + type: bool + default: true + vpc_tor_delay_restore_timer: + description: + - vPC delay restore timer for ToR switches in seconds. + type: int + default: 30 + fabric_vpc_domain_id: + description: + - Enable the same vPC domain ID for all vPC pairs. Not recommended. + type: bool + default: false + shared_vpc_domain_id: + description: + - vPC domain ID to be used on all vPC pairs. + type: int + default: 1 + fabric_vpc_qos: + description: + - QoS on spines for guaranteed delivery of vPC Fabric Peering communication. + type: bool + default: false + fabric_vpc_qos_policy_name: + description: + - QoS policy name. Should be the same on all spines. + type: str + default: spine_qos_for_fabric_vpc_peering + enable_peer_switch: + description: + - Enable the vPC peer-switch feature on ToR switches. + type: bool + default: false + per_vrf_loopback_auto_provision: + description: + - Auto provision an IPv4 loopback on a VTEP on VRF attachment. + - Enabling this option auto-provisions loopback on existing VRF attachments and also + when Edit, QuickAttach, or Multiattach actions are performed. + type: bool + default: false + per_vrf_loopback_ip_range: + description: + - Prefix pool to assign IPv4 addresses to loopbacks on VTEPs on a per VRF basis. + type: str + default: "10.5.0.0/22" + per_vrf_loopback_auto_provision_ipv6: + description: + - Auto provision an IPv6 loopback on a VTEP on VRF attachment. + type: bool + default: false + per_vrf_loopback_ipv6_range: + description: + - Prefix pool to assign IPv6 addresses to loopbacks on VTEPs on a per VRF basis. + type: str + default: "fd00::a05:0/112" + vrf_template: + description: + - Default overlay VRF template for leafs. + type: str + default: Default_VRF_Universal + network_template: + description: + - Default overlay network template for leafs. + type: str + default: Default_Network_Universal + vrf_extension_template: + description: + - Default overlay VRF template for borders. + type: str + default: Default_VRF_Extension_Universal + network_extension_template: + description: + - Default overlay network template for borders. + type: str + default: Default_Network_Extension_Universal + performance_monitoring: + description: + - If enabled, switch metrics are collected through periodic SNMP polling. + Alternative to real-time telemetry. + type: bool + default: false + tenant_dhcp: + description: + - Enable tenant DHCP. + type: bool + default: true + advertise_physical_ip: + description: + - For primary VTEP IP advertisement as next-hop of prefix routes. + type: bool + default: false + advertise_physical_ip_on_border: + description: + - Enable advertise-pip on vPC borders and border gateways only. + Applicable only when vPC advertise-pip is not enabled. + type: bool + default: true + bgp_authentication: + description: + - Enable BGP authentication. + type: bool + default: false + bgp_authentication_key_type: + description: + - BGP key encryption type. 3 - 3DES, 6 - Cisco type 6, 7 - Cisco type 7. + type: str + default: 3des + choices: [ 3des, type6, type7 ] + bgp_authentication_key: + description: + - Encrypted BGP authentication key based on type. + type: str + default: "" + bfd: + description: + - Enable BFD. Valid for IPv4 underlay only. + type: bool + default: false + bfd_ibgp: + description: + - Enable BFD for iBGP. + type: bool + default: false + bfd_authentication: + description: + - Enable BFD authentication. Valid for P2P interfaces only. + type: bool + default: false + bfd_authentication_key_id: + description: + - BFD authentication key ID. + type: int + default: 100 + bfd_authentication_key: + description: + - Encrypted SHA1 secret value. + type: str + default: "" + pim_hello_authentication: + description: + - Enable PIM hello authentication. Valid for IPv4 underlay only. + type: bool + default: false + pim_hello_authentication_key: + description: + - PIM hello authentication key. 3DES encrypted. + type: str + default: "" + nxapi: + description: + - Enable NX-API over HTTPS. + type: bool + default: false + nxapi_http: + description: + - Enable NX-API over HTTP. + type: bool + default: false + nxapi_https_port: + description: + - HTTPS port for NX-API (1-65535). + type: int + default: 443 + nxapi_http_port: + description: + - HTTP port for NX-API (1-65535). + type: int + default: 80 + day0_bootstrap: + description: + - Automatic IP assignment for POAP. + type: bool + default: false + bootstrap_subnet_collection: + description: + - List of IPv4 or IPv6 subnets to be used for bootstrap. + - When O(state=merged), omitting this option preserves the existing collection. + - When O(state=merged), providing this option replaces the entire collection with the supplied list. + - Under O(state=merged), entries in this list are not merged item-by-item. + - Under O(state=merged), removing one entry from the playbook removes it from the fabric, and setting an empty list clears the collection. + - When O(state=replaced), this option is also treated as the exact desired collection. + - When O(state=replaced), omitting this option resets the collection to its default empty value. + type: list + elements: dict + suboptions: + start_ip: + description: + - Starting IP address of the bootstrap range. + type: str + required: true + end_ip: + description: + - Ending IP address of the bootstrap range. + type: str + required: true + default_gateway: + description: + - Default gateway for the bootstrap subnet. + type: str + required: true + subnet_prefix: + description: + - Subnet prefix length (8-30). + type: int + required: true + local_dhcp_server: + description: + - Automatic IP assignment for POAP from local DHCP server. + type: bool + default: false + dhcp_protocol_version: + description: + - IP protocol version for local DHCP server. + type: str + default: dhcpv4 + choices: [ dhcpv4, dhcpv6 ] + dhcp_start_address: + description: + - DHCP scope start address for switch POAP. + type: str + default: "" + dhcp_end_address: + description: + - DHCP scope end address for switch POAP. + type: str + default: "" + management_gateway: + description: + - Default gateway for management VRF on the switch. + type: str + default: "" + management_ipv4_prefix: + description: + - Switch management IP subnet prefix for IPv4. + type: int + default: 24 + management_ipv6_prefix: + description: + - Switch management IP subnet prefix for IPv6. + type: int + default: 64 + netflow_settings: + description: + - Netflow configuration settings. + type: dict + suboptions: + netflow: + description: + - Enable netflow collection. + type: bool + default: false + netflow_exporter_collection: + description: + - List of netflow exporters. + type: list + elements: dict + suboptions: + exporter_name: + description: + - Name of the netflow exporter. + type: str + required: true + exporter_ip: + description: + - IP address of the netflow collector. + type: str + required: true + vrf: + description: + - VRF name for the exporter. + type: str + default: management + source_interface_name: + description: + - Source interface name. + type: str + required: true + udp_port: + description: + - UDP port for netflow export (1-65535). + type: int + netflow_record_collection: + description: + - List of netflow records. + type: list + elements: dict + suboptions: + record_name: + description: + - Name of the netflow record. + type: str + required: true + record_template: + description: + - Template type for the record. + type: str + required: true + layer2_record: + description: + - Enable layer 2 record fields. + type: bool + default: false + netflow_monitor_collection: + description: + - List of netflow monitors. + type: list + elements: dict + suboptions: + monitor_name: + description: + - Name of the netflow monitor. + type: str + required: true + record_name: + description: + - Associated record name. + type: str + required: true + exporter1_name: + description: + - Primary exporter name. + type: str + required: true + exporter2_name: + description: + - Secondary exporter name. + type: str + default: "" + real_time_backup: + description: + - Backup hourly only if there is any config deployment since last backup. + type: bool + scheduled_backup: + description: + - Enable backup at the specified time daily. + type: bool + scheduled_backup_time: + description: + - Time (UTC) in 24 hour format to take a daily backup if enabled (00:00 to 23:59). + type: str + default: "" + leaf_tor_id_range: + description: + - Use specific vPC/Port-channel ID range for leaf-tor pairings. + type: bool + default: false + leaf_tor_vpc_port_channel_id_range: + description: + - vPC/Port-channel ID range (minimum 1, maximum 4096), used for auto-allocating + vPC/Port-Channel IDs for leaf-tor pairings. + type: str + default: "1-499" + allow_vlan_on_leaf_tor_pairing: + description: + - Set trunk allowed VLAN to none or all for leaf-tor pairing port-channels. + type: str + default: none + choices: [ none, all ] + ntp_server_collection: + description: + - List of NTP server IPv4/IPv6 addresses and/or hostnames. + type: list + elements: str + ntp_server_vrf_collection: + description: + - NTP Server VRFs. One VRF for all NTP servers or a list of VRFs, one per NTP server. + type: list + elements: str + dns_collection: + description: + - List of IPv4 and IPv6 DNS addresses. + type: list + elements: str + dns_vrf_collection: + description: + - DNS Server VRFs. One VRF for all DNS servers or a list of VRFs, one per DNS server. + type: list + elements: str + syslog_server_collection: + description: + - List of syslog server IPv4/IPv6 addresses and/or hostnames. + type: list + elements: str + syslog_server_vrf_collection: + description: + - Syslog Server VRFs. One VRF for all syslog servers or a list of VRFs, one per syslog server. + type: list + elements: str + syslog_severity_collection: + description: + - List of syslog severity values, one per syslog server. + type: list + elements: int + banner: + description: + - Message of the Day (motd) banner. Delimiter char (very first char is delimiter char) + followed by message ending with delimiter. + type: str + default: "" + extra_config_leaf: + description: + - Additional CLIs added after interface configurations for all switches with a VTEP + unless they have some spine role. + type: str + default: "" + extra_config_spine: + description: + - Additional CLIs added after interface configurations for all switches with some spine role. + type: str + default: "" + extra_config_tor: + description: + - Additional CLIs added after interface configurations for all ToRs. + type: str + default: "" + extra_config_intra_fabric_links: + description: + - Additional CLIs for all intra-fabric links. + type: str + default: "" + extra_config_aaa: + description: + - AAA configurations. + type: str + default: "" + extra_config_nxos_bootstrap: + description: + - Additional CLIs required during device bootup/login e.g. AAA/Radius. + type: str + default: "" + aaa: + description: + - Include AAA configs from Manageability tab during device bootup. + type: bool + default: false + pre_interface_config_leaf: + description: + - Additional CLIs added before interface configurations for all switches with a VTEP + unless they have some spine role. + type: str + default: "" + pre_interface_config_spine: + description: + - Additional CLIs added before interface configurations for all switches with some spine role. + type: str + default: "" + pre_interface_config_tor: + description: + - Additional CLIs added before interface configurations for all ToRs. + type: str + default: "" + greenfield_debug_flag: + description: + - Allow switch configuration to be cleared without a reload when preserveConfig is set to false. + type: str + default: disable + choices: [ enable, disable ] + interface_statistics_load_interval: + description: + - Interface statistics load interval in seconds. + type: int + default: 10 + nve_hold_down_timer: + description: + - NVE source interface hold-down time in seconds. + type: int + default: 180 + next_generation_oam: + description: + - Enable the Next Generation (NG) OAM feature for all switches in the fabric + to aid in troubleshooting VXLAN EVPN fabrics. + type: bool + default: true + ngoam_south_bound_loop_detect: + description: + - Enable the Next Generation (NG) OAM southbound loop detection. + type: bool + default: false + ngoam_south_bound_loop_detect_probe_interval: + description: + - Next Generation (NG) OAM southbound loop detection probe interval in seconds. + type: int + default: 300 + ngoam_south_bound_loop_detect_recovery_interval: + description: + - Next Generation (NG) OAM southbound loop detection recovery interval in seconds. + type: int + default: 600 + strict_config_compliance_mode: + description: + - Enable bi-directional compliance checks to flag additional configs in the running + config that are not in the intent/expected config. + type: bool + default: false + advanced_ssh_option: + description: + - Enable AAA IP Authorization. Enable only when IP Authorization is enabled + in the AAA Server. + type: bool + default: false + copp_policy: + description: + - Fabric wide CoPP policy. Customized CoPP policy should be provided when C(manual) is selected. + type: str + default: strict + choices: [ dense, lenient, moderate, strict, manual ] + power_redundancy_mode: + description: + - Default power supply mode for NX-OS switches. + type: str + default: redundant + choices: [ redundant, combined, inputSrcRedundant ] + heartbeat_interval: + description: + - XConnect heartbeat interval for periodic link status checks. + type: int + default: 190 + snmp_trap: + description: + - Configure ND as a receiver for SNMP traps. + type: bool + default: true + cdp: + description: + - Enable CDP on management interface. + type: bool + default: false + real_time_interface_statistics_collection: + description: + - Enable real time interface statistics collection. Valid for NX-OS only. + type: bool + default: false + tcam_allocation: + description: + - TCAM commands are automatically generated for VxLAN and vPC Fabric Peering when enabled. + type: bool + default: true + allow_smart_switch_onboarding: + description: + - Enable onboarding of smart switches to Hypershield for firewall service. + type: bool + default: false + default_queuing_policy: + description: + - Enable default queuing policies. + type: bool + default: false + default_queuing_policy_cloudscale: + description: + - Queuing policy for all 92xx, -EX, -FX, -FX2, -FX3, -GX series switches in the fabric. + type: str + default: queuing_policy_default_8q_cloudscale + default_queuing_policy_r_series: + description: + - Queueing policy for all Nexus R-series switches. + type: str + default: queuing_policy_default_r_series + default_queuing_policy_other: + description: + - Queuing policy for all other switches in the fabric. + type: str + default: queuing_policy_default_other + aiml_qos: + description: + - Configures QoS and Queuing Policies specific to N9K Cloud Scale (CS) and + Silicon One (S1) switch fabric for AI network workloads. + type: bool + default: false + aiml_qos_policy: + description: + - Queuing policy based on predominant fabric link speed. + C(User-defined) allows for custom configuration. + type: str + default: 400G + choices: [ 800G, 400G, 100G, 25G, User-defined ] + roce_v2: + description: + - DSCP for RDMA traffic. Numeric (0-63) with ranges/comma, or named values + (af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, + cs1, cs2, cs3, cs4, cs5, cs6, cs7, default, ef). + type: str + default: "26" + cnp: + description: + - DSCP value for Congestion Notification. Numeric (0-63) with ranges/comma, or named values + (af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, + cs1, cs2, cs3, cs4, cs5, cs6, cs7, default, ef). + type: str + default: "48" + wred_min: + description: + - WRED minimum threshold in kbytes. + type: int + default: 950 + wred_max: + description: + - WRED maximum threshold in kbytes. + type: int + default: 3000 + wred_drop_probability: + description: + - WRED drop probability percentage. + type: int + default: 7 + wred_weight: + description: + - Influences how quickly WRED reacts to queue depth changes. + type: int + default: 0 + bandwidth_remaining: + description: + - Percentage of remaining bandwidth allocated to AI traffic queues. + type: int + default: 50 + dlb: + description: + - Enables fabric-level Dynamic Load Balancing (DLB) configuration. + Inter-Switch-Links (ISL) will be configured as DLB interfaces. + type: bool + default: false + dlb_mode: + description: + - Select system-wide flowlet, per-packet (packet spraying) or policy driven mixed mode. + Mixed mode is supported on Silicon One (S1) platform only. + type: str + default: flowlet + choices: [ flowlet, per-packet, policy-driven-flowlet, policy-driven-per-packet, policy-driven-mixed-mode ] + dlb_mixed_mode_default: + description: + - Default load balancing mode for policy driven mixed mode DLB. + type: str + default: ecmp + choices: [ ecmp, flowlet, per-packet ] + flowlet_aging: + description: + - Flowlet aging timer in microseconds. Valid range depends on platform. + Cloud Scale (CS) 1-2000000 (default 500), Silicon One (S1) 1-1024 (default 256). + type: int + flowlet_dscp: + description: + - DSCP values for flowlet load balancing. Numeric (0-63) with ranges/comma, or named values + (af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, + cs1, cs2, cs3, cs4, cs5, cs6, cs7, default, ef). + type: str + default: "" + per_packet_dscp: + description: + - DSCP values for per-packet load balancing. Numeric (0-63) with ranges/comma, or named values + (af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, + cs1, cs2, cs3, cs4, cs5, cs6, cs7, default, ef). + type: str + default: "" + ai_load_sharing: + description: + - Enable IP load sharing using source and destination address for AI workloads. + type: bool + default: false + priority_flow_control_watch_interval: + description: + - Acceptable values from 101 to 1000 (milliseconds). + Leave blank for system default (100ms). + type: int + ptp: + description: + - Enable Precision Time Protocol (PTP). + type: bool + default: false + ptp_loopback_id: + description: + - Precision Time Protocol source loopback ID. + type: int + default: 0 + ptp_domain_id: + description: + - Multiple independent PTP clocking subdomains on a single network. + type: int + default: 0 + private_vlan: + description: + - Enable PVLAN on switches except spines and super spines. + type: bool + default: false + default_private_vlan_secondary_network_template: + description: + - Default PVLAN secondary network template. + type: str + default: Pvlan_Secondary_Network + macsec: + description: + - Enable MACsec in the fabric. MACsec fabric parameters are used for configuring + MACsec on a fabric link if MACsec is enabled on the link. + type: bool + default: false + macsec_cipher_suite: + description: + - Configure MACsec cipher suite. + type: str + default: GCM-AES-XPN-256 + choices: [ GCM-AES-128, GCM-AES-256, GCM-AES-XPN-128, GCM-AES-XPN-256 ] + macsec_key_string: + description: + - MACsec primary key string. Cisco Type 7 encrypted octet string. + type: str + default: "" + macsec_algorithm: + description: + - MACsec primary cryptographic algorithm. AES_128_CMAC or AES_256_CMAC. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + macsec_fallback_key_string: + description: + - MACsec fallback key string. Cisco Type 7 encrypted octet string. + type: str + default: "" + macsec_fallback_algorithm: + description: + - MACsec fallback cryptographic algorithm. AES_128_CMAC or AES_256_CMAC. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + macsec_report_timer: + description: + - MACsec operational status periodic report timer in minutes. + type: int + default: 5 + enable_dpu_pinning: + description: + - Enable pinning of VRFs and networks to specific DPUs on smart switches. + type: bool + default: false + connectivity_domain_name: + description: + - Domain name to connect to Hypershield. + type: str + hypershield_connectivity_proxy_server: + description: + - IPv4 address, IPv6 address, or DNS name of the proxy server for Hypershield communication. + type: str + hypershield_connectivity_proxy_server_port: + description: + - Proxy port number for communication with Hypershield. + type: int + hypershield_connectivity_source_intf: + description: + - Loopback interface on smart switch for communication with Hypershield. + type: str + telemetry_settings: + description: + - Telemetry configuration settings. + type: dict + suboptions: + flow_collection: + description: + - Flow collection settings. + type: dict + suboptions: + traffic_analytics: + description: + - Traffic analytics state. + type: str + default: enabled + traffic_analytics_scope: + description: + - Traffic analytics scope. + type: str + default: intraFabric + operating_mode: + description: + - Operating mode. + type: str + default: flowTelemetry + udp_categorization: + description: + - UDP categorization. + type: str + default: enabled + microburst: + description: + - Microburst detection settings. + type: dict + suboptions: + microburst: + description: + - Enable microburst detection. + type: bool + default: false + sensitivity: + description: + - Microburst sensitivity level. + type: str + default: low + analysis_settings: + description: + - Telemetry analysis settings. + type: dict + suboptions: + is_enabled: + description: + - Enable telemetry analysis. + type: bool + default: false + nas: + description: + - NAS telemetry configuration. + type: dict + suboptions: + server: + description: + - NAS server address. + type: str + default: "" + export_settings: + description: + - NAS export settings. + type: dict + suboptions: + export_type: + description: + - Export type. + type: str + default: full + export_format: + description: + - Export format. + type: str + default: json + energy_management: + description: + - Energy management settings. + type: dict + suboptions: + cost: + description: + - Energy cost per unit. + type: float + default: 1.2 + external_streaming_settings: + description: + - External streaming settings. + type: dict + suboptions: + email: + description: + - Email streaming configuration. + type: list + elements: dict + message_bus: + description: + - Message bus configuration. + type: list + elements: dict + syslog: + description: + - Syslog streaming configuration. + type: dict + webhooks: + description: + - Webhook configuration. + type: list + elements: dict + state: + description: + - The desired state of the fabric resources on the Cisco Nexus Dashboard. + - Use O(state=merged) to create new fabrics and update existing ones as defined in the configuration. + Resources on ND that are not specified in the configuration will be left unchanged. + - Use O(state=replaced) to replace the fabric configuration specified in the configuration. + Any settings not explicitly provided will revert to their defaults. + - Use O(state=overridden) to enforce the configuration as the single source of truth. + Any fabric existing on ND but not present in the configuration will be deleted. Use with extra caution. + - Use O(state=deleted) to remove the fabrics specified in the configuration from the Cisco Nexus Dashboard. + type: str + default: merged + choices: [ merged, replaced, overridden, deleted ] +extends_documentation_fragment: +- cisco.nd.modules +- cisco.nd.check_mode +notes: +- This module is only supported on Nexus Dashboard having version 4.1.0 or higher. +- Only AI/ML eBGP VXLAN fabric type (C(aimlVxlanEbgp)) is supported by this module. +- When using O(state=replaced) with only required fields, all optional management settings revert to their defaults. +- The O(config.management.bgp_asn) field is optional when O(config.management.bgp_asn_auto_allocation) is C(true). +- The O(config.management.bgp_asn) field is required when O(config.management.bgp_asn_auto_allocation) is C(false). +- O(config.management.site_id) defaults to the value of O(config.management.bgp_asn) if not provided. +- The default O(config.management.vpc_peer_keep_alive_option) for eBGP fabrics is C(management), unlike iBGP fabrics. +""" + +EXAMPLES = r""" +- name: Create an AI/ML eBGP VXLAN fabric using state merged (with auto ASN allocation) + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: merged + config: + - fabric_name: my_ai_ebgp_fabric + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn_auto_allocation: true + bgp_asn_range: "65000-65535" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00aa" + performance_monitoring: false + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 2 + rendezvous_point_loopback_id: 254 + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + advertise_physical_ip: false + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9216 + l2_host_interface_mtu: 9216 + tenant_dhcp: true + nxapi: false + nxapi_https_port: 443 + nxapi_http: false + nxapi_http_port: 80 + snmp_trap: true + anycast_border_gateway_advertise_physical_ip: false + greenfield_debug_flag: disable + tcam_allocation: true + real_time_interface_statistics_collection: false + interface_statistics_load_interval: 10 + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.33.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.5.0.0/22" + banner: "" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + register: result + +- name: Create an AI/ML eBGP VXLAN fabric with a static BGP ASN + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: merged + config: + - fabric_name: my_ai_ebgp_fabric_static + category: fabric + management: + type: aimlVxlanEbgp + bgp_asn: "65001" + bgp_asn_auto_allocation: false + site_id: "65001" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00aa" + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + register: result + +- name: Update specific fields on an existing AI/ML eBGP fabric using state merged (partial update) + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: merged + config: + - fabric_name: my_ai_ebgp_fabric + category: fabric + management: + bgp_asn_range: "65100-65199" + anycast_gateway_mac: "2020.0000.00bb" + performance_monitoring: true + register: result + +- name: Create or fully replace an AI/ML eBGP VXLAN fabric using state replaced + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: replaced + config: + - fabric_name: my_ai_ebgp_fabric + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65004" + bgp_asn_auto_allocation: false + site_id: "65004" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00dd" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.3.0/25" + rendezvous_point_count: 3 + rendezvous_point_loopback_id: 253 + vpc_peer_link_vlan: "3700" + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 300 + vpc_delay_restore_timer: 120 + vpc_peer_link_port_channel_id: "600" + advertise_physical_ip: true + vpc_domain_id_range: "1-800" + fabric_mtu: 9000 + l2_host_interface_mtu: 9000 + tenant_dhcp: false + snmp_trap: false + anycast_border_gateway_advertise_physical_ip: true + greenfield_debug_flag: disable + tcam_allocation: false + real_time_interface_statistics_collection: true + interface_statistics_load_interval: 30 + bgp_loopback_ip_range: "10.22.0.0/22" + nve_loopback_ip_range: "10.23.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.252.0/24" + intra_fabric_subnet_range: "10.24.0.0/16" + l2_vni_range: "40000-59000" + l3_vni_range: "60000-69000" + network_vlan_range: "2400-3099" + vrf_vlan_range: "2100-2399" + banner: "^ Managed by Ansible ^" + register: result + +- name: Replace fabric with only required fields (all optional settings revert to defaults) + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: replaced + config: + - fabric_name: my_ai_ebgp_fabric + category: fabric + management: + type: aimlVxlanEbgp + bgp_asn: "65004" + bgp_asn_auto_allocation: false + site_id: "65004" + banner: "^ Managed by Ansible ^" + register: result + +- name: Enforce exact fabric inventory using state overridden (deletes unlisted fabrics) + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: overridden + config: + - fabric_name: fabric_east + category: fabric + location: + latitude: 40.7128 + longitude: -74.0060 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65010" + bgp_asn_auto_allocation: false + site_id: "65010" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.0010" + replication_mode: multicast + multicast_group_subnet: "239.1.10.0/25" + bgp_loopback_ip_range: "10.10.0.0/22" + nve_loopback_ip_range: "10.11.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.10.0/24" + intra_fabric_subnet_range: "10.12.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + - fabric_name: fabric_west + category: fabric + location: + latitude: 34.0522 + longitude: -118.2437 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65020" + bgp_asn_auto_allocation: false + site_id: "65020" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.0020" + replication_mode: multicast + multicast_group_subnet: "239.1.20.0/25" + bgp_loopback_ip_range: "10.20.0.0/22" + nve_loopback_ip_range: "10.21.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.20.0/24" + intra_fabric_subnet_range: "10.22.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + register: result + +- name: Delete a specific AI/ML eBGP fabric using state deleted + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: deleted + config: + - fabric_name: my_ai_ebgp_fabric + register: result + +- name: Delete multiple AI/ML eBGP fabrics in a single task + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + state: deleted + config: + - fabric_name: fabric_east + - fabric_name: fabric_west + - fabric_name: fabric_old + register: result +""" + +RETURN = r""" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.nd.plugins.module_utils.nd import nd_argument_spec +from ansible_collections.cisco.nd.plugins.module_utils.nd_state_machine import NDStateMachine +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ai_ebgp_vxlan import FabricAiEbgpVxlanModel +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.manage_fabric_ai_ebgp_vxlan import ManageAiEbgpVxlanFabricOrchestrator +from ansible_collections.cisco.nd.plugins.module_utils.common.exceptions import NDStateMachineError + + +def main(): + argument_spec = nd_argument_spec() + argument_spec.update(FabricAiEbgpVxlanModel.get_argument_spec()) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + try: + # Initialize StateMachine + nd_state_machine = NDStateMachine( + module=module, + model_orchestrator=ManageAiEbgpVxlanFabricOrchestrator, + ) + + # Manage state + nd_state_machine.manage_state() + + module.exit_json(**nd_state_machine.output.format()) + + except NDStateMachineError as e: + module.fail_json(msg=str(e)) + except Exception as e: + module.fail_json(msg=f"Module execution failed: {str(e)}") + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/nd_manage_fabric_ai_ibgp_vxlan.py b/plugins/modules/nd_manage_fabric_ai_ibgp_vxlan.py new file mode 100644 index 00000000..6d0fb430 --- /dev/null +++ b/plugins/modules/nd_manage_fabric_ai_ibgp_vxlan.py @@ -0,0 +1,1707 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2026, Matt Tarkington (@mtarking) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: nd_manage_fabric_ai_ibgp_vxlan +version_added: "2.0.0" +short_description: Manage AI/ML iBGP VXLAN fabrics on Cisco Nexus Dashboard +description: +- Manage AI/ML iBGP VXLAN fabrics on Cisco Nexus Dashboard (ND). +- It supports creating, updating, replacing, and deleting AI/ML iBGP VXLAN fabrics. +- AI/ML iBGP VXLAN fabrics are optimized for AI and machine learning workloads using iBGP underlay with VXLAN overlay. +- The AI/ML iBGP VXLAN fabric type (C(aimlVxlanIbgp)) shares the same management properties as the standard iBGP VXLAN + fabric type (C(vxlanIbgp)), but is specifically designated for AI/ML workloads. +author: +- Matt Tarkington (@mtarking) +options: + config: + description: + - The list of AI/ML iBGP VXLAN fabrics to configure. + type: list + elements: dict + suboptions: + fabric_name: + description: + - The name of the fabric. + - Only letters, numbers, underscores, and hyphens are allowed. + - The O(config.fabric_name) must be defined when creating, updating or deleting a fabric. + type: str + required: true + category: + description: + - The resource category. + type: str + default: fabric + location: + description: + - The geographic location of the fabric. + type: dict + suboptions: + latitude: + description: + - Latitude coordinate of the fabric location (-90 to 90). + type: float + required: true + longitude: + description: + - Longitude coordinate of the fabric location (-180 to 180). + type: float + required: true + license_tier: + description: + - The License Tier for fabric. + type: str + default: essentials + choices: [ essentials, advantage, premier ] + alert_suspend: + description: + - The Alert Suspend state configured on the fabric. + type: str + default: disabled + choices: [ enabled, disabled ] + telemetry_collection: + description: + - Enable telemetry collection. + type: bool + default: true + telemetry_collection_type: + description: + - The telemetry collection method. + type: str + default: inBand + choices: [ inBand, outOfBand ] + telemetry_streaming_protocol: + description: + - The Telemetry Streaming Protocol. + type: str + default: ipv4 + choices: [ ipv4, ipv6 ] + telemetry_source_interface: + description: + - Telemetry Source Interface Loopback ID, only valid if Telemetry Collection is set to inBand. + type: str + default: loopback0 + telemetry_source_vrf: + description: + - VRF over which telemetry is streamed, valid only if Telemetry Collection is set to inBand. + type: str + default: default + security_domain: + description: + - The Security Domain associated with the fabric. + type: str + default: all + management: + description: + - The AI/ML iBGP VXLAN management configuration for the fabric. + - Properties are grouped by template section for readability in the module documentation source. + type: dict + suboptions: + # General + type: + description: + - The fabric management type. Must be C(aimlVxlanIbgp) for AI/ML iBGP VXLAN fabrics. + type: str + default: aimlVxlanIbgp + choices: [ aimlVxlanIbgp ] + bgp_asn: + description: + - The BGP Autonomous System Number for the fabric. + - Accepts a plain integer (1-4294967295) or dotted notation (1-65535.0-65535). + type: str + required: true + underlay_ipv6: + description: + - Enable IPv6 underlay. + type: bool + default: false + fabric_interface_type: + description: + - The fabric interface type. Numbered (Point-to-Point) or unnumbered. + type: str + default: p2p + choices: [ p2p, unNumbered ] + link_state_routing_protocol: + description: + - The underlay link-state routing protocol. + type: str + default: ospf + choices: [ ospf, isis ] + target_subnet_mask: + description: + - The target subnet mask for intra-fabric links (24-31). + type: int + default: 30 + ipv6_link_local: + description: + - Enable IPv6 link-local addressing. + type: bool + default: true + ipv6_subnet_target_mask: + description: + - The IPv6 subnet target mask. + type: int + default: 126 + route_reflector_count: + description: + - The number of spines acting as BGP route reflectors. + type: int + default: 2 + choices: [ 2, 4 ] + anycast_gateway_mac: + description: + - The anycast gateway MAC address in xxxx.xxxx.xxxx format. + type: str + default: 2020.0000.00aa + performance_monitoring: + description: + - Enable performance monitoring. + type: bool + default: false + + # Replication + replication_mode: + description: + - The multicast replication mode. + type: str + default: multicast + choices: [ multicast, ingress ] + multicast_group_subnet: + description: + - The multicast group subnet. + type: str + default: "239.1.1.0/25" + ipv6_multicast_group_subnet: + description: + - The IPv6 multicast group subnet. + type: str + default: "ff1e::/121" + auto_generate_multicast_group_address: + description: + - Automatically generate multicast group addresses. + type: bool + default: false + underlay_multicast_group_address_limit: + description: + - The underlay multicast group address limit. + - The maximum supported value is 128 for NX-OS version 10.2(1) or earlier and 512 for versions above 10.2(1). + type: int + default: 128 + choices: [ 128, 512 ] + tenant_routed_multicast: + description: + - Enable tenant routed multicast. + type: bool + default: false + tenant_routed_multicast_ipv6: + description: + - Enable tenant routed multicast for IPv6. + type: bool + default: false + rendezvous_point_count: + description: + - The number of spines acting as Rendezvous-Points (RPs). + type: int + default: 2 + choices: [ 2, 4 ] + rendezvous_point_mode: + description: + - Multicast rendezvous point mode. For IPv6 underlay, use C(asm) only. + type: str + default: asm + choices: [ asm, bidir ] + rendezvous_point_loopback_id: + description: + - The rendezvous point loopback interface ID (0-1023). + type: int + default: 254 + phantom_rendezvous_point_loopback_id1: + description: + - Underlay phantom RP loopback primary ID for PIM Bi-dir deployments. + type: int + default: 2 + phantom_rendezvous_point_loopback_id2: + description: + - Underlay phantom RP loopback secondary ID for PIM Bi-dir deployments. + type: int + default: 3 + phantom_rendezvous_point_loopback_id3: + description: + - Underlay phantom RP loopback tertiary ID for PIM Bi-dir deployments. + type: int + default: 4 + phantom_rendezvous_point_loopback_id4: + description: + - Underlay phantom RP loopback quaternary ID for PIM Bi-dir deployments. + type: int + default: 5 + anycast_rendezvous_point_ip_range: + description: + - The anycast rendezvous point IP address pool. + type: str + default: "10.254.254.0/24" + ipv6_anycast_rendezvous_point_ip_range: + description: + - The IPv6 anycast rendezvous point IP address pool. + type: str + default: "fd00::254:254:0/118" + l3vni_multicast_group: + description: + - Default underlay multicast group IPv4 address assigned for every overlay VRF. + type: str + default: "239.1.1.0" + l3_vni_ipv6_multicast_group: + description: + - Default underlay multicast group IPv6 address assigned for every overlay VRF. + type: str + default: "ff1e::" + mvpn_vrf_route_import_id: + description: + - Enable MVPN VRI ID generation for Tenant Routed Multicast with IPv4 underlay. + type: bool + default: true + mvpn_vrf_route_import_id_range: + description: + - MVPN VRI ID range (minimum 1, maximum 65535) for vPC. + - Applicable when TRM is enabled with IPv6 underlay, or mvpn_vrf_route_import_id is enabled with IPv4 underlay. + type: str + default: "" + vrf_route_import_id_reallocation: + description: + - One time VRI ID re-allocation based on MVPN VRI ID Range. + type: bool + default: false + + # vPC + vpc_domain_id_range: + description: + - The vPC domain ID range. + type: str + default: "1-1000" + vpc_peer_link_vlan: + description: + - The vPC peer link VLAN ID. + type: str + default: "3600" + vpc_peer_link_enable_native_vlan: + description: + - Enable native VLAN on the vPC peer link. + type: bool + default: false + vpc_peer_keep_alive_option: + description: + - The vPC peer keep-alive option. + type: str + default: management + choices: [ loopback, management ] + vpc_auto_recovery_timer: + description: + - The vPC auto recovery timer in seconds (240-3600). + type: int + default: 360 + vpc_delay_restore_timer: + description: + - The vPC delay restore timer in seconds (1-3600). + type: int + default: 150 + vpc_peer_link_port_channel_id: + description: + - The vPC peer link port-channel ID. + type: str + default: "500" + vpc_ipv6_neighbor_discovery_sync: + description: + - Enable vPC IPv6 neighbor discovery synchronization. + type: bool + default: true + vpc_layer3_peer_router: + description: + - Enable vPC layer-3 peer router. + type: bool + default: true + vpc_tor_delay_restore_timer: + description: + - The vPC TOR delay restore timer. + type: int + default: 30 + fabric_vpc_domain_id: + description: + - Enable fabric vPC domain ID. + type: bool + default: false + shared_vpc_domain_id: + description: + - The shared vPC domain ID. + type: int + default: 1 + fabric_vpc_qos: + description: + - Enable fabric vPC QoS. + type: bool + default: false + fabric_vpc_qos_policy_name: + description: + - The fabric vPC QoS policy name. + type: str + default: spine_qos_for_fabric_vpc_peering + enable_peer_switch: + description: + - Enable peer switch. + type: bool + default: false + advertise_physical_ip: + description: + - Advertise physical IP address for NVE loopback. + type: bool + default: false + advertise_physical_ip_on_border: + description: + - Advertise physical IP address on border switches. + type: bool + default: true + anycast_border_gateway_advertise_physical_ip: + description: + - Enable anycast border gateway to advertise physical IP. + type: bool + default: false + allow_vlan_on_leaf_tor_pairing: + description: + - "Set trunk allowed VLAN to 'none' or 'all' for leaf-TOR pairing port-channels." + type: str + default: none + choices: [ none, all ] + leaf_tor_id_range: + description: + - Use specific vPC/Port-channel ID range for leaf-TOR pairings. + type: bool + default: false + leaf_tor_vpc_port_channel_id_range: + description: + - Specify vPC/Port-channel ID range (minimum 1, maximum 4096) for leaf-TOR pairings. + type: str + default: "1-499" + + # Protocols + ospf_area_id: + description: + - The OSPF area ID. + type: str + default: "0.0.0.0" + bgp_loopback_id: + description: + - The BGP loopback interface ID (0-1023). + type: int + default: 0 + nve_loopback_id: + description: + - The NVE loopback interface ID (0-1023). + type: int + default: 1 + anycast_loopback_id: + description: + - Underlay Anycast Loopback ID. Used for vPC Peering in VXLANv6 Fabrics. + type: int + default: 10 + auto_bgp_neighbor_description: + description: + - Enable automatic BGP neighbor description. + type: bool + default: true + ibgp_peer_template: + description: + - The iBGP peer template name. + type: str + default: "" + leaf_ibgp_peer_template: + description: + - The leaf iBGP peer template name. + type: str + default: "" + link_state_routing_tag: + description: + - The link state routing tag. + type: str + default: UNDERLAY + bgp_authentication: + description: + - Enable BGP authentication. + type: bool + default: false + bgp_authentication_key_type: + description: + - "BGP key encryption type: 3 - 3DES, 6 - Cisco type 6, 7 - Cisco type 7." + type: str + default: 3des + choices: [ 3des, type6, type7 ] + bgp_authentication_key: + description: + - The BGP authentication key. + type: str + default: "" + bfd: + description: + - Enable BFD globally. + type: bool + default: false + bfd_ibgp: + description: + - Enable BFD for iBGP sessions. + type: bool + default: false + bfd_ospf: + description: + - Enable BFD for OSPF. + type: bool + default: false + bfd_isis: + description: + - Enable BFD for IS-IS. + type: bool + default: false + bfd_pim: + description: + - Enable BFD for PIM. + type: bool + default: false + bfd_authentication: + description: + - Enable BFD authentication. + type: bool + default: false + bfd_authentication_key_id: + description: + - The BFD authentication key ID. + type: int + default: 100 + bfd_authentication_key: + description: + - The BFD authentication key. + type: str + default: "" + ospf_authentication: + description: + - Enable OSPF authentication. + type: bool + default: false + ospf_authentication_key_id: + description: + - The OSPF authentication key ID. + type: int + default: 127 + ospf_authentication_key: + description: + - The OSPF authentication key. + type: str + default: "" + pim_hello_authentication: + description: + - Enable PIM hello authentication. + type: bool + default: false + pim_hello_authentication_key: + description: + - The PIM hello authentication key. + type: str + default: "" + isis_level: + description: + - The IS-IS level. + type: str + default: level-2 + choices: [ level-1, level-2 ] + isis_area_number: + description: + - The IS-IS area number. + type: str + default: "0001" + isis_point_to_point: + description: + - Enable IS-IS point-to-point. + type: bool + default: true + isis_authentication: + description: + - Enable IS-IS authentication. + type: bool + default: false + isis_authentication_keychain_name: + description: + - The IS-IS authentication keychain name. + type: str + default: "" + isis_authentication_keychain_key_id: + description: + - The IS-IS authentication keychain key ID. + type: int + default: 127 + isis_authentication_key: + description: + - The IS-IS authentication key. + type: str + default: "" + isis_overload: + description: + - Enable IS-IS overload bit. + type: bool + default: true + isis_overload_elapse_time: + description: + - The IS-IS overload elapse time in seconds. + type: int + default: 60 + + # Security + security_group_tag: + description: + - Enable Security Group Tag (SGT) support. + type: bool + default: false + security_group_tag_prefix: + description: + - The SGT prefix. + type: str + default: SG_ + security_group_tag_mac_segmentation: + description: + - Enable SGT MAC segmentation. + type: bool + default: false + security_group_tag_id_range: + description: + - The SGT ID range. + type: str + default: "10000-14000" + security_group_tag_preprovision: + description: + - Enable SGT pre-provisioning. + type: bool + default: false + security_group_status: + description: + - The security group status. + type: str + default: disabled + choices: [ enabled, enabledStrict, enabledLoose, enablePending, enablePendingStrict, enablePendingLoose, disablePending, disabled ] + macsec: + description: + - Enable MACsec on intra-fabric links. + type: bool + default: false + macsec_cipher_suite: + description: + - The MACsec cipher suite. + type: str + default: GCM-AES-XPN-256 + choices: [ GCM-AES-128, GCM-AES-256, GCM-AES-XPN-128, GCM-AES-XPN-256 ] + macsec_key_string: + description: + - The MACsec primary key string. + type: str + default: "" + macsec_algorithm: + description: + - The MACsec primary cryptographic algorithm. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + macsec_fallback_key_string: + description: + - The MACsec fallback key string. + type: str + default: "" + macsec_fallback_algorithm: + description: + - The MACsec fallback cryptographic algorithm. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + macsec_report_timer: + description: + - The MACsec report timer. + type: int + default: 5 + vrf_lite_macsec: + description: + - Enable MACsec on DCI links. + type: bool + default: false + vrf_lite_macsec_cipher_suite: + description: + - The DCI MACsec cipher suite. + type: str + default: GCM-AES-XPN-256 + choices: [ GCM-AES-128, GCM-AES-256, GCM-AES-XPN-128, GCM-AES-XPN-256 ] + vrf_lite_macsec_key_string: + description: + - The DCI MACsec primary key string (Cisco Type 7 Encrypted Octet String). + type: str + default: "" + vrf_lite_macsec_algorithm: + description: + - The DCI MACsec primary cryptographic algorithm. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + vrf_lite_macsec_fallback_key_string: + description: + - The DCI MACsec fallback key string (Cisco Type 7 Encrypted Octet String). + - This parameter is used when DCI link has QKD disabled. + type: str + default: "" + vrf_lite_macsec_fallback_algorithm: + description: + - The DCI MACsec fallback cryptographic algorithm. + - This parameter is used when DCI link has QKD disabled. + type: str + default: AES_128_CMAC + choices: [ AES_128_CMAC, AES_256_CMAC ] + quantum_key_distribution: + description: + - Enable quantum key distribution. + type: bool + default: false + quantum_key_distribution_profile_name: + description: + - The quantum key distribution profile name. + type: str + default: "" + key_management_entity_server_ip: + description: + - The key management entity server IP address. + type: str + default: "" + key_management_entity_server_port: + description: + - The key management entity server port. + type: int + default: 0 + trustpoint_label: + description: + - The trustpoint label for TLS authentication. + type: str + default: "" + skip_certificate_verification: + description: + - Skip verification of incoming certificate. + type: bool + default: false + + # Advanced + site_id: + description: + - The site identifier for the fabric (for EVPN Multi-Site support). + - Must be a numeric value between 1 and 281474976710655. + - Defaults to the value of O(config.management.bgp_asn) if not provided. + type: str + default: "" + overlay_mode: + description: + - The overlay configuration mode. + type: str + default: cli + choices: [ cli, config-profile ] + vrf_template: + description: + - The VRF template name. + type: str + default: Default_VRF_Universal + network_template: + description: + - The network template name. + type: str + default: Default_Network_Universal + vrf_extension_template: + description: + - The VRF extension template name. + type: str + default: Default_VRF_Extension_Universal + network_extension_template: + description: + - The network extension template name. + type: str + default: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: + description: + - Enable L3 VNI no-VLAN default option. + type: bool + default: false + fabric_mtu: + description: + - The fabric MTU size (1500-9216). + type: int + default: 9216 + l2_host_interface_mtu: + description: + - The L2 host interface MTU size (1500-9216). + type: int + default: 9216 + tenant_dhcp: + description: + - Enable tenant DHCP. + type: bool + default: true + snmp_trap: + description: + - Enable SNMP traps. + type: bool + default: true + cdp: + description: + - Enable CDP. + type: bool + default: false + tcam_allocation: + description: + - Enable TCAM allocation. + type: bool + default: true + real_time_interface_statistics_collection: + description: + - Enable real-time interface statistics collection. + type: bool + default: false + interface_statistics_load_interval: + description: + - The interface statistics load interval in seconds. + type: int + default: 10 + greenfield_debug_flag: + description: + - Allow switch configuration to be cleared without a reload when preserveConfig is set to false. + type: str + default: disable + choices: [ enable, disable ] + nxapi: + description: + - Enable NX-API (HTTPS). + type: bool + default: false + nxapi_https_port: + description: + - The NX-API HTTPS port (1-65535). + type: int + default: 443 + nxapi_http: + description: + - Enable NX-API over HTTP. + type: bool + default: false + nxapi_http_port: + description: + - The NX-API HTTP port (1-65535). + type: int + default: 80 + default_queuing_policy: + description: + - Enable default queuing policies. + type: bool + default: false + default_queuing_policy_cloudscale: + description: + - Queuing policy for all 92xx, -EX, -FX, -FX2, -FX3, -GX series switches in the fabric. + type: str + default: queuing_policy_default_8q_cloudscale + default_queuing_policy_r_series: + description: + - Queuing policy for all Nexus R-series switches. + type: str + default: queuing_policy_default_r_series + default_queuing_policy_other: + description: + - Queuing policy for all other switches in the fabric. + type: str + default: queuing_policy_default_other + aiml_qos: + description: + - Enable AI/ML QoS. Configures QoS and queuing policies specific to N9K Cloud Scale and Silicon One switch fabric + for AI network workloads. + type: bool + default: false + aiml_qos_policy: + description: + - Queuing policy based on predominant fabric link speed. + type: str + default: 400G + choices: [ 800G, 400G, 100G, 25G, User-defined ] + roce_v2: + description: + - DSCP for RDMA traffic. Numeric (0-63) with ranges/comma, or named values. + type: str + default: "26" + cnp: + description: + - DSCP value for Congestion Notification. Numeric (0-63) with ranges/comma, or named values. + type: str + default: "48" + wred_min: + description: + - WRED minimum threshold (in kbytes). + type: int + default: 950 + wred_max: + description: + - WRED maximum threshold (in kbytes). + type: int + default: 3000 + wred_drop_probability: + description: + - WRED drop probability percentage. + type: int + default: 7 + wred_weight: + description: + - Influences how quickly WRED reacts to queue depth changes. + type: int + default: 0 + bandwidth_remaining: + description: + - Percentage of remaining bandwidth allocated to AI traffic queues. + type: int + default: 50 + dlb: + description: + - Enable fabric-level Dynamic Load Balancing (DLB). Inter-Switch-Links will be configured as DLB interfaces. + type: bool + default: false + dlb_mode: + description: + - "Select system-wide DLB mode: flowlet, per-packet (packet spraying), or policy driven mixed mode. + Mixed mode is supported on Silicon One (S1) platform only." + type: str + default: flowlet + choices: [ flowlet, per-packet, policy-driven-flowlet, policy-driven-per-packet, policy-driven-mixed-mode ] + dlb_mixed_mode_default: + description: + - Default load balancing mode for policy driven mixed mode DLB. + type: str + default: ecmp + choices: [ ecmp, flowlet, per-packet ] + flowlet_aging: + description: + - "Flowlet aging timer in microseconds. Valid range depends on platform: Cloud Scale (CS)=1-2000000, + Silicon One (S1)=1-1024." + type: int + default: 1 + flowlet_dscp: + description: + - DSCP values for flowlet load balancing. Numeric (0-63) with ranges/comma, or named values. + type: str + default: "" + per_packet_dscp: + description: + - DSCP values for per-packet load balancing. Numeric (0-63) with ranges/comma, or named values. + type: str + default: "" + ai_load_sharing: + description: + - Enable IP load sharing using source and destination address for AI workloads. + type: bool + default: false + priority_flow_control_watch_interval: + description: + - PFC watch interval in milliseconds (101-1000). Leave blank for system default (100ms). + type: int + default: 101 + ptp: + description: + - Enable Precision Time Protocol (PTP). + type: bool + default: false + ptp_loopback_id: + description: + - The PTP loopback ID. + type: int + default: 0 + ptp_domain_id: + description: + - The PTP domain ID for multiple independent PTP clocking subdomains on a single network. + type: int + default: 0 + ptp_vlan_id: + description: + - Precision Time Protocol (PTP) source VLAN ID. SVI used for PTP source on ToRs. + type: int + default: 2 + stp_root_option: + description: + - "Which protocol to use for configuring root bridge: rpvst+ (Rapid Per-VLAN Spanning Tree), + mst (Multiple Spanning Tree), or unmanaged (STP Root not managed by ND)." + type: str + default: unmanaged + choices: [ rpvst+, mst, unmanaged ] + stp_vlan_range: + description: + - The STP VLAN range (minimum 1, maximum 4094). + type: str + default: "1-3967" + mst_instance_range: + description: + - The MST instance range (minimum 0, maximum 4094). + type: str + default: "0" + stp_bridge_priority: + description: + - The STP bridge priority. + type: int + default: 0 + mpls_handoff: + description: + - Enable MPLS handoff. + type: bool + default: false + mpls_loopback_identifier: + description: + - The MPLS loopback identifier used for VXLAN to MPLS SR/LDP Handoff. + type: int + default: 101 + mpls_isis_area_number: + description: + - IS-IS area number for DCI MPLS link. Used only if routing protocol on DCI MPLS link is IS-IS. + type: str + default: "0001" + mpls_loopback_ip_range: + description: + - The MPLS loopback IP address pool. + type: str + default: "10.101.0.0/25" + private_vlan: + description: + - Enable PVLAN on switches except spines and super spines. + type: bool + default: false + default_private_vlan_secondary_network_template: + description: + - Default PVLAN secondary network template. + type: str + default: Pvlan_Secondary_Network + nve_hold_down_timer: + description: + - The NVE hold-down timer in seconds. + type: int + default: 180 + next_generation_oam: + description: + - Enable the Next Generation (NG) OAM feature for all switches in the fabric. + type: bool + default: true + ngoam_south_bound_loop_detect: + description: + - Enable the Next Generation (NG) OAM southbound loop detection. + type: bool + default: false + ngoam_south_bound_loop_detect_probe_interval: + description: + - Set NG OAM southbound loop detection probe interval in seconds. + type: int + default: 300 + ngoam_south_bound_loop_detect_recovery_interval: + description: + - Set NG OAM southbound loop detection recovery interval in seconds. + type: int + default: 600 + strict_config_compliance_mode: + description: + - Enable bi-directional compliance checks to flag additional configs in the running config + that are not in the intent/expected config. + type: bool + default: false + advanced_ssh_option: + description: + - Enable AAA IP Authorization. Enable only when IP Authorization is enabled in the AAA Server. + type: bool + default: false + copp_policy: + description: + - The fabric wide CoPP policy. Customized CoPP policy should be provided when C(manual) is selected. + type: str + default: strict + choices: [ dense, lenient, moderate, strict, manual ] + power_redundancy_mode: + description: + - Default power supply mode for NX-OS switches. + type: str + default: redundant + choices: [ redundant, combined, inputSrcRedundant ] + host_interface_admin_state: + description: + - Enable host interface admin state. + type: bool + default: true + heartbeat_interval: + description: + - The heartbeat interval. + type: int + default: 190 + policy_based_routing: + description: + - Enable policy-based routing. + type: bool + default: false + brownfield_network_name_format: + description: + - The brownfield network name format. + type: str + default: "Auto_Net_VNI$$VNI$$_VLAN$$VLAN_ID$$" + brownfield_skip_overlay_network_attachments: + description: + - Skip brownfield overlay network attachments. + type: bool + default: false + + # Freeform + extra_config_leaf: + description: + - Extra freeform configuration applied to leaf switches. + type: str + default: "" + extra_config_spine: + description: + - Extra freeform configuration applied to spine switches. + type: str + default: "" + extra_config_tor: + description: + - Extra freeform configuration applied to TOR switches. + type: str + default: "" + extra_config_intra_fabric_links: + description: + - Extra freeform configuration applied to intra-fabric links. + type: str + default: "" + pre_interface_config_leaf: + description: + - Additional CLIs added before interface configurations for all switches with a VTEP + unless they have some spine role. + type: str + default: "" + pre_interface_config_spine: + description: + - Additional CLIs added before interface configurations for all switches with some spine role. + type: str + default: "" + pre_interface_config_tor: + description: + - Additional CLIs added before interface configurations for all ToRs. + type: str + default: "" + + # Resources + static_underlay_ip_allocation: + description: + - Enable static underlay IP allocation. + type: bool + default: false + bgp_loopback_ip_range: + description: + - The BGP loopback IP address pool. + type: str + default: "10.2.0.0/22" + nve_loopback_ip_range: + description: + - The NVE loopback IP address pool. + type: str + default: "10.3.0.0/22" + bgp_loopback_ipv6_range: + description: + - The BGP loopback IPv6 address pool. + type: str + default: "fd00::a02:0/119" + nve_loopback_ipv6_range: + description: + - The NVE loopback IPv6 address pool. + type: str + default: "fd00::a03:0/118" + intra_fabric_subnet_range: + description: + - The intra-fabric subnet IP address pool. + type: str + default: "10.4.0.0/16" + ipv6_subnet_range: + description: + - The IPv6 subnet range. + type: str + default: "fd00::a04:0/112" + router_id_range: + description: + - The BGP router ID range in IPv4 subnet format. Used for IPv6 underlay. + type: str + default: "10.2.0.0/23" + l2_vni_range: + description: + - The Layer 2 VNI range. + type: str + default: "30000-49000" + l3_vni_range: + description: + - The Layer 3 VNI range. + type: str + default: "50000-59000" + network_vlan_range: + description: + - The network VLAN range. + type: str + default: "2300-2999" + vrf_vlan_range: + description: + - The VRF VLAN range. + type: str + default: "2000-2299" + sub_interface_dot1q_range: + description: + - The sub-interface 802.1q range (minimum 2, maximum 4093). + type: str + default: "2-511" + vrf_lite_auto_config: + description: + - "VRF Lite Inter-Fabric Connection deployment options. If C(back2BackAndToExternal) is selected, + VRF Lite IFCs are auto created between border devices of two Easy Fabrics, and between + border devices in Easy Fabric and edge routers in External Fabric." + type: str + default: manual + choices: [ manual, back2BackAndToExternal ] + vrf_lite_subnet_range: + description: + - The VRF lite subnet IP address pool. + type: str + default: "10.33.0.0/16" + vrf_lite_subnet_target_mask: + description: + - The VRF lite subnet target mask. + type: int + default: 30 + auto_unique_vrf_lite_ip_prefix: + description: + - Enable auto unique VRF lite IP prefix. + type: bool + default: false + auto_symmetric_vrf_lite: + description: + - Enable auto symmetric VRF lite. + type: bool + default: false + auto_vrf_lite_default_vrf: + description: + - Enable auto VRF lite for the default VRF. + type: bool + default: false + auto_symmetric_default_vrf: + description: + - Enable auto symmetric default VRF. + type: bool + default: false + default_vrf_redistribution_bgp_route_map: + description: + - Route Map used to redistribute BGP routes to IGP in default VRF in auto created VRF Lite IFC links. + type: str + default: extcon-rmap-filter + per_vrf_loopback_auto_provision: + description: + - Enable per-VRF loopback auto-provisioning. + type: bool + default: false + per_vrf_loopback_ip_range: + description: + - The per-VRF loopback IP address pool. + type: str + default: "10.5.0.0/22" + per_vrf_loopback_auto_provision_ipv6: + description: + - Enable per-VRF loopback auto-provisioning for IPv6. + type: bool + default: false + per_vrf_loopback_ipv6_range: + description: + - The per-VRF loopback IPv6 address pool. + type: str + default: "fd00::a05:0/112" + per_vrf_unique_loopback_auto_provision: + description: + - Auto provision a unique IPv4 loopback on a VTEP on VRF attachment. + - This option and per VRF per VTEP loopback auto-provisioning are mutually exclusive. + type: bool + default: false + per_vrf_unique_loopback_ip_range: + description: + - Prefix pool to assign unique IPv4 addresses to loopbacks on VTEPs on a per VRF basis. + type: str + default: "10.6.0.0/22" + per_vrf_unique_loopback_auto_provision_v6: + description: + - Auto provision a unique IPv6 loopback on a VTEP on VRF attachment. + type: bool + default: false + per_vrf_unique_loopback_ipv6_range: + description: + - Prefix pool to assign unique IPv6 addresses to loopbacks on VTEPs on a per VRF basis. + type: str + default: "fd00::a06:0/112" + ip_service_level_agreement_id_range: + description: + - The IP SLA ID range. + type: str + default: "10000-19999" + object_tracking_number_range: + description: + - The object tracking number range. + type: str + default: "100-299" + route_map_sequence_number_range: + description: + - The route map sequence number range (minimum 1, maximum 65534). + type: str + default: "1-65534" + service_network_vlan_range: + description: + - Per Switch Overlay Service Network VLAN Range (minimum 2, maximum 4094). + type: str + default: "3000-3199" + + # Manageability + inband_management: + description: + - Manage switches with only inband connectivity. + type: bool + default: false + aaa: + description: + - Enable AAA. + type: bool + default: false + extra_config_aaa: + description: + - Extra freeform AAA configuration. + type: str + default: "" + banner: + description: + - The fabric banner text displayed on switch login. + type: str + default: "" + ntp_server_collection: + description: + - The list of NTP server IP addresses. + type: list + elements: str + ntp_server_vrf_collection: + description: + - The list of VRFs for NTP servers. + type: list + elements: str + dns_collection: + description: + - The list of DNS server IP addresses. + type: list + elements: str + dns_vrf_collection: + description: + - The list of VRFs for DNS servers. + type: list + elements: str + syslog_server_collection: + description: + - The list of syslog server IP addresses. + type: list + elements: str + syslog_server_vrf_collection: + description: + - The list of VRFs for syslog servers. + type: list + elements: str + syslog_severity_collection: + description: + - The list of syslog severity levels (0-7). + type: list + elements: int + + # Hypershield + allow_smart_switch_onboarding: + description: + - Enable onboarding of smart switches to Hypershield for firewall service. + type: bool + default: false + connectivity_domain_name: + description: + - Domain name to connect to Hypershield. + type: str + hypershield_connectivity_proxy_server: + description: + - IPv4 address, IPv6 address, or DNS name of the proxy server for Hypershield communication. + type: str + hypershield_connectivity_proxy_server_port: + description: + - Proxy port number for communication with Hypershield. + type: int + hypershield_connectivity_source_intf: + description: + - Loopback interface on smart switch for communication with Hypershield. + type: str + + # Bootstrap + day0_bootstrap: + description: + - Enable day-0 bootstrap (POAP). + type: bool + default: false + local_dhcp_server: + description: + - Enable local DHCP server for bootstrap. + type: bool + default: false + dhcp_protocol_version: + description: + - The IP protocol version for local DHCP server. + type: str + default: dhcpv4 + choices: [ dhcpv4, dhcpv6 ] + dhcp_start_address: + description: + - The DHCP start address for bootstrap. + type: str + default: "" + dhcp_end_address: + description: + - The DHCP end address for bootstrap. + type: str + default: "" + management_gateway: + description: + - The management gateway for bootstrap. + type: str + default: "" + management_ipv4_prefix: + description: + - The management IPv4 prefix length for bootstrap. + type: int + default: 24 + management_ipv6_prefix: + description: + - The management IPv6 prefix length for bootstrap. + type: int + default: 64 + bootstrap_subnet_collection: + description: + - List of IPv4 or IPv6 subnets to be used for bootstrap. + - When O(state=merged), omitting this option preserves the existing collection. + - When O(state=merged), providing this option replaces the entire collection with the supplied list. + - Under O(state=merged), entries in this list are not merged item-by-item. + - Under O(state=merged), removing one entry from the playbook removes it from the fabric, and setting an empty list clears the collection. + - When O(state=replaced), this option is also treated as the exact desired collection. + - When O(state=replaced), omitting this option resets the collection to its default empty value. + type: list + elements: dict + suboptions: + start_ip: + description: + - Starting IP address of the bootstrap range. + type: str + required: true + end_ip: + description: + - Ending IP address of the bootstrap range. + type: str + required: true + default_gateway: + description: + - Default gateway for bootstrap subnet. + type: str + required: true + subnet_prefix: + description: + - Subnet prefix length (8-30). + type: int + required: true + seed_switch_core_interfaces: + description: + - Seed switch fabric interfaces. Core-facing interface list on seed switch. + type: list + elements: str + spine_switch_core_interfaces: + description: + - Spine switch fabric interfaces. Core-facing interface list on all spines. + type: list + elements: str + inband_dhcp_servers: + description: + - List of external DHCP server IP addresses (Max 3). + type: list + elements: str + extra_config_nxos_bootstrap: + description: + - Additional CLIs required during device bootup/login (e.g. AAA/Radius). + type: str + default: "" + unnumbered_bootstrap_loopback_id: + description: + - Bootstrap Seed Switch Loopback Interface ID. + type: int + default: 253 + unnumbered_dhcp_start_address: + description: + - Switch Loopback DHCP Scope Start Address. Must be a subset of IGP/BGP Loopback Prefix Pool. + type: str + default: "" + unnumbered_dhcp_end_address: + description: + - Switch Loopback DHCP Scope End Address. Must be a subset of IGP/BGP Loopback Prefix Pool. + type: str + default: "" + + # Configuration Backup + real_time_backup: + description: + - Enable real-time backup. + type: bool + default: false + scheduled_backup: + description: + - Enable scheduled backup. + type: bool + default: false + scheduled_backup_time: + description: + - The scheduled backup time. + type: str + default: "" + + # Flow Monitor + netflow_settings: + description: + - Settings associated with netflow. + type: dict + suboptions: + netflow: + description: + - Enable netflow collection. + type: bool + default: false + netflow_exporter_collection: + description: + - List of netflow exporters. + type: list + elements: dict + suboptions: + exporter_name: + description: + - Name of the netflow exporter. + type: str + required: true + exporter_ip: + description: + - IP address of the netflow collector. + type: str + required: true + vrf: + description: + - VRF name for the exporter. + type: str + default: management + source_interface_name: + description: + - Source interface name. + type: str + required: true + udp_port: + description: + - UDP port for netflow export (1-65535). + type: int + netflow_record_collection: + description: + - List of netflow records. + type: list + elements: dict + suboptions: + record_name: + description: + - Name of the netflow record. + type: str + required: true + record_template: + description: + - Template type for the record. + type: str + required: true + layer2_record: + description: + - Enable layer 2 record fields. + type: bool + default: false + netflow_monitor_collection: + description: + - List of netflow monitors. + type: list + elements: dict + suboptions: + monitor_name: + description: + - Name of the netflow monitor. + type: str + required: true + record_name: + description: + - Associated record name. + type: str + required: true + exporter1_name: + description: + - Primary exporter name. + type: str + required: true + exporter2_name: + description: + - Secondary exporter name. + type: str + default: "" + state: + description: + - The desired state of the fabric resources on the Cisco Nexus Dashboard. + - Use O(state=merged) to create new fabrics and update existing ones as defined in the configuration. + Resources on ND that are not specified in the configuration will be left unchanged. + - Use O(state=replaced) to replace the fabric configuration specified in the configuration. + Any settings not explicitly provided will revert to their defaults. + - Use O(state=overridden) to enforce the configuration as the single source of truth. + Any fabric existing on ND but not present in the configuration will be deleted. Use with extra caution. + - Use O(state=deleted) to remove the fabrics specified in the configuration from the Cisco Nexus Dashboard. + type: str + default: merged + choices: [ merged, replaced, overridden, deleted ] +extends_documentation_fragment: +- cisco.nd.modules +- cisco.nd.check_mode +notes: +- This module is only supported on Nexus Dashboard having version 4.1.0 or higher. +- Only AI/ML iBGP VXLAN fabric type (C(aimlVxlanIbgp)) is supported by this module. +- When using O(state=replaced) with only required fields, all optional management settings revert to their defaults. +- The O(config.management.bgp_asn) field is required when creating a fabric. +- O(config.management.site_id) defaults to the value of O(config.management.bgp_asn) if not provided. +""" + +EXAMPLES = r""" +- name: Create an AI/ML iBGP VXLAN fabric using state merged + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + state: merged + config: + - fabric_name: ai_ibgp_fabric_1 + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65001" + site_id: "65001" + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00aa" + performance_monitoring: false + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 2 + rendezvous_point_loopback_id: 254 + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: loopback + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + advertise_physical_ip: false + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + allow_smart_switch_onboarding: true + register: result + +- name: Update specific fields on an existing AI/ML fabric using state merged (partial update) + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + state: merged + config: + - fabric_name: ai_ibgp_fabric_1 + category: fabric + management: + bgp_asn: "65002" + site_id: "65002" + anycast_gateway_mac: "2020.0000.00bb" + performance_monitoring: true + register: result + +- name: Delete an AI/ML iBGP VXLAN fabric + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + state: deleted + config: + - fabric_name: ai_ibgp_fabric_1 + register: result + +- name: Delete multiple AI/ML fabrics in a single task + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + state: deleted + config: + - fabric_name: ai_ibgp_fabric_1 + - fabric_name: ai_ibgp_fabric_2 + register: result +""" + +RETURN = r""" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.nd.plugins.module_utils.nd import nd_argument_spec +from ansible_collections.cisco.nd.plugins.module_utils.nd_state_machine import NDStateMachine +from ansible_collections.cisco.nd.plugins.module_utils.models.manage_fabric.manage_fabric_ai_ibgp_vxlan import FabricAiIbgpVxlanModel +from ansible_collections.cisco.nd.plugins.module_utils.orchestrators.manage_fabric_ai_ibgp_vxlan import ManageAiIbgpVxlanFabricOrchestrator +from ansible_collections.cisco.nd.plugins.module_utils.common.exceptions import NDStateMachineError + + +def main(): + argument_spec = nd_argument_spec() + argument_spec.update(FabricAiIbgpVxlanModel.get_argument_spec()) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + try: + # Initialize StateMachine + nd_state_machine = NDStateMachine( + module=module, + model_orchestrator=ManageAiIbgpVxlanFabricOrchestrator, + ) + + # Manage state + nd_state_machine.manage_state() + + module.exit_json(**nd_state_machine.output.format()) + + except NDStateMachineError as e: + module.fail_json(msg=str(e)) + except Exception as e: + module.fail_json(msg=f"Module execution failed: {str(e)}") + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ebgp.yaml b/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ebgp.yaml new file mode 100644 index 00000000..c431b488 --- /dev/null +++ b/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ebgp.yaml @@ -0,0 +1,614 @@ +--- +# Test code for the ND modules +# Copyright: (c) 2026, Cisco Systems + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have a Nexus Dashboard host, username and password + ansible.builtin.fail: + msg: 'Please define the following variables: ansible_host, ansible_user and ansible_password.' + when: ansible_host is not defined or ansible_user is not defined or ansible_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + nd_info: &nd_info + output_level: '{{ api_key_output_level | default("debug") }}' + +############################################################################# +# CLEANUP - Ensure clean state before tests +############################################################################# +- name: Clean up any existing test fabrics before starting tests + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ebgp_test_fabric_merged }}" + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + tags: always + +############################################################################# +# TEST 1: STATE MERGED - Create fabric using merged state +############################################################################# +- name: "TEST 1a: Create AI eBGP VXLAN fabric using state merged (first run)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: merged + config: + - "{{ {'fabric_name': ai_ebgp_test_fabric_merged} | combine(fabric_config_ai_ebgp) }}" + register: merged_result_1 + tags: [test_merged, test_merged_create] + +- name: "TEST 1a: Verify fabric was created using merged state" + assert: + that: + - merged_result_1 is changed + - merged_result_1 is not failed + fail_msg: "AI eBGP VXLAN fabric creation with state merged failed" + success_msg: "AI eBGP VXLAN fabric successfully created with state merged" + tags: [test_merged, test_merged_create] + +- name: "TEST 1b: Create fabric using state merged (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: merged + config: + - "{{ {'fabric_name': ai_ebgp_test_fabric_merged} | combine(fabric_config_ai_ebgp) }}" + register: merged_result_2 + tags: [test_merged, test_merged_idempotent] + +- name: "TEST 1b: Verify merged state is idempotent" + assert: + that: + - merged_result_2 is not changed + - merged_result_2 is not failed + fail_msg: "Merged state is not idempotent - should not change when run twice with same config" + success_msg: "Merged state is idempotent - no changes on second run" + tags: [test_merged, test_merged_idempotent] + +- name: "TEST 1c: Update fabric using state merged (modify existing)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: merged + config: + - fabric_name: "{{ ai_ebgp_test_fabric_merged }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65002" + bgp_asn_auto_allocation: false + site_id: "65002" + bgp_as_mode: multiAS + bgp_allow_as_in_num: 1 + bgp_max_path: 4 + auto_configure_ebgp_evpn_peering: true + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00bb" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 2 + rendezvous_point_loopback_id: 254 + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + advertise_physical_ip: false + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9216 + l2_host_interface_mtu: 9216 + tenant_dhcp: true + nxapi: false + nxapi_https_port: 443 + nxapi_http: false + nxapi_http_port: 80 + snmp_trap: true + anycast_border_gateway_advertise_physical_ip: false + greenfield_debug_flag: disable + tcam_allocation: true + real_time_interface_statistics_collection: false + interface_statistics_load_interval: 10 + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.33.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.5.0.0/22" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + register: merged_result_3 + tags: [test_merged, test_merged_update] + +- name: "TEST 1c: Verify fabric was updated using merged state" + assert: + that: + - merged_result_3 is changed + - merged_result_3 is not failed + fail_msg: "AI eBGP VXLAN fabric update with state merged failed" + success_msg: "AI eBGP VXLAN fabric successfully updated with state merged" + tags: [test_merged, test_merged_update] + +############################################################################# +# VALIDATION: Query ai_ebgp_test_fabric_merged and validate expected changes +############################################################################# +- name: "VALIDATION 1: Authenticate with ND to get token" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/login" + method: POST + headers: + Content-Type: "application/json" + body_format: json + body: + domain: "{{ ansible_httpapi_login_domain | default('local') }}" + userName: "{{ ansible_user }}" + userPasswd: "{{ ansible_password }}" + validate_certs: false + return_content: true + status_code: + - 200 + register: nd_auth_response + tags: [test_merged, test_merged_validation] + delegate_to: localhost + +- name: "VALIDATION 1: Query ai_ebgp_test_fabric_merged configuration from ND" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/api/v1/manage/fabrics/{{ ai_ebgp_test_fabric_merged }}" + method: GET + headers: + Authorization: "Bearer {{ nd_auth_response.json.jwttoken }}" + Content-Type: "application/json" + validate_certs: false + return_content: true + status_code: + - 200 + - 404 + register: merged_fabric_query + tags: [test_merged, test_merged_validation] + delegate_to: localhost + +- name: "VALIDATION 1: Parse fabric configuration response" + set_fact: + merged_fabric_config: "{{ merged_fabric_query.json }}" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1a: Verify fabric type is aimlVxlanEbgp" + assert: + that: + - merged_fabric_config.management.type == "aimlVxlanEbgp" + fail_msg: >- + Fabric type validation failed - expected aimlVxlanEbgp, + got {{ merged_fabric_config.management.type }} + success_msg: "Fabric type correctly set to aimlVxlanEbgp" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1b: Verify changed properties after merge" + assert: + that: + - merged_fabric_config.management.bgpAsn == "65002" + - merged_fabric_config.management.siteId == "65002" + - merged_fabric_config.management.anycastGatewayMac == "2020.0000.00bb" + - merged_fabric_config.management.performanceMonitoring == true + fail_msg: >- + Changed properties validation failed. + bgpAsn: {{ merged_fabric_config.management.bgpAsn }} (expected 65002), + siteId: {{ merged_fabric_config.management.siteId }} (expected 65002), + anycastGatewayMac: {{ merged_fabric_config.management.anycastGatewayMac }} (expected 2020.0000.00bb), + performanceMonitoring: {{ merged_fabric_config.management.performanceMonitoring }} (expected true) + success_msg: "All 4 changed properties updated correctly" + tags: [test_merged, test_merged_validation] + +############################################################################# +# TEST 2: STATE REPLACED - Create and manage fabric using replaced state +############################################################################# +- name: "TEST 2a: Create AI eBGP VXLAN fabric using state replaced (first run)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65004" + bgp_asn_auto_allocation: false + site_id: "65004" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00dd" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.3.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 4 + rendezvous_point_loopback_id: 253 + vpc_peer_link_vlan: "3700" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 300 + vpc_delay_restore_timer: 120 + vpc_peer_link_port_channel_id: "600" + advertise_physical_ip: true + vpc_domain_id_range: "1-800" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9000 + l2_host_interface_mtu: 9000 + tenant_dhcp: false + nxapi: false + nxapi_https_port: 443 + nxapi_http: true + nxapi_http_port: 80 + snmp_trap: false + anycast_border_gateway_advertise_physical_ip: true + greenfield_debug_flag: disable + tcam_allocation: false + real_time_interface_statistics_collection: true + interface_statistics_load_interval: 30 + bgp_loopback_ip_range: "10.22.0.0/22" + nve_loopback_ip_range: "10.23.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.252.0/24" + intra_fabric_subnet_range: "10.24.0.0/16" + l2_vni_range: "40000-59000" + l3_vni_range: "60000-69000" + network_vlan_range: "2400-3099" + vrf_vlan_range: "2100-2399" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.53.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.25.0.0/22" + banner: "^ AI eBGP Updated via replaced state ^" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + register: replaced_result_1 + tags: [test_replaced, test_replaced_create] + +- name: "TEST 2a: Verify fabric was created using replaced state" + assert: + that: + - replaced_result_1 is changed + - replaced_result_1 is not failed + fail_msg: "AI eBGP VXLAN fabric creation with state replaced failed" + success_msg: "AI eBGP VXLAN fabric successfully created with state replaced" + tags: [test_replaced, test_replaced_create] + +- name: "TEST 2b: Create fabric using state replaced (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65004" + bgp_asn_auto_allocation: false + site_id: "65004" + bgp_as_mode: multiAS + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00dd" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.3.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 4 + rendezvous_point_loopback_id: 253 + vpc_peer_link_vlan: "3700" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 300 + vpc_delay_restore_timer: 120 + vpc_peer_link_port_channel_id: "600" + advertise_physical_ip: true + vpc_domain_id_range: "1-800" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9000 + l2_host_interface_mtu: 9000 + tenant_dhcp: false + nxapi: false + nxapi_https_port: 443 + nxapi_http: true + nxapi_http_port: 80 + snmp_trap: false + anycast_border_gateway_advertise_physical_ip: true + greenfield_debug_flag: disable + tcam_allocation: false + real_time_interface_statistics_collection: true + interface_statistics_load_interval: 30 + bgp_loopback_ip_range: "10.22.0.0/22" + nve_loopback_ip_range: "10.23.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.252.0/24" + intra_fabric_subnet_range: "10.24.0.0/16" + l2_vni_range: "40000-59000" + l3_vni_range: "60000-69000" + network_vlan_range: "2400-3099" + vrf_vlan_range: "2100-2399" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.53.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.25.0.0/22" + banner: "^ AI eBGP Updated via replaced state ^" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + register: replaced_result_2 + tags: [test_replaced, test_replaced_idempotent] + +- name: "TEST 2b: Verify replaced state is idempotent" + assert: + that: + - replaced_result_2 is not changed + - replaced_result_2 is not failed + fail_msg: "Replaced state is not idempotent - should not change when run twice with same config" + success_msg: "Replaced state is idempotent - no changes on second run" + tags: [test_replaced, test_replaced_idempotent] + +- name: "TEST 2c: Update fabric using state replaced (complete replacement with minimal config)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65004" + bgp_asn_auto_allocation: false + site_id: "65004" + banner: "^ AI eBGP Updated via replaced state ^" + register: replaced_result_3 + tags: [test_replaced, test_replaced_update] + +- name: "TEST 2c: Verify fabric was completely replaced" + assert: + that: + - replaced_result_3 is changed + - replaced_result_3 is not failed + fail_msg: "AI eBGP VXLAN fabric replacement with state replaced failed" + success_msg: "AI eBGP VXLAN fabric successfully replaced with state replaced" + tags: [test_replaced, test_replaced_update] + +############################################################################# +# VALIDATION: Query ai_ebgp_test_fabric_replaced and validate +############################################################################# +- name: "VALIDATION 2: Authenticate with ND to get token" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/login" + method: POST + headers: + Content-Type: "application/json" + body_format: json + body: + domain: "{{ ansible_httpapi_login_domain | default('local') }}" + userName: "{{ ansible_user }}" + userPasswd: "{{ ansible_password }}" + validate_certs: false + return_content: true + status_code: + - 200 + register: nd_auth_response_2 + tags: [test_replaced, test_replaced_validation] + delegate_to: localhost + +- name: "VALIDATION 2: Query ai_ebgp_test_fabric_replaced configuration from ND" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/api/v1/manage/fabrics/{{ ai_ebgp_test_fabric_replaced }}" + method: GET + headers: + Authorization: "Bearer {{ nd_auth_response_2.json.jwttoken }}" + Content-Type: "application/json" + validate_certs: false + return_content: true + status_code: + - 200 + - 404 + register: replaced_fabric_query + tags: [test_replaced, test_replaced_validation] + delegate_to: localhost + +- name: "VALIDATION 2: Parse fabric configuration response" + set_fact: + replaced_fabric_config: "{{ replaced_fabric_query.json }}" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2a: Verify fabric type is preserved as aimlVxlanEbgp" + assert: + that: + - replaced_fabric_config.management.type == "aimlVxlanEbgp" + fail_msg: >- + Fabric type validation failed after replace - expected aimlVxlanEbgp, + got {{ replaced_fabric_config.management.type }} + success_msg: "Fabric type correctly preserved as aimlVxlanEbgp after replace" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2b: Verify explicitly specified properties in replace" + assert: + that: + - replaced_fabric_config.management.bgpAsn == "65004" + - replaced_fabric_config.management.siteId == "65004" + - replaced_fabric_config.management.banner == "^ AI eBGP Updated via replaced state ^" + fail_msg: >- + Explicitly specified properties validation failed. + success_msg: "All 3 explicitly specified properties set correctly" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2c: Verify properties reverted to defaults after replace" + assert: + that: + - replaced_fabric_config.management.anycastGatewayMac == "2020.0000.00aa" + - replaced_fabric_config.management.performanceMonitoring == false + - replaced_fabric_config.management.fabricMtu == 9216 + - replaced_fabric_config.management.l2HostInterfaceMtu == 9216 + - replaced_fabric_config.management.replicationMode == "multicast" + - replaced_fabric_config.management.multicastGroupSubnet == "239.1.1.0/25" + - replaced_fabric_config.management.rendezvousPointCount == 2 + - replaced_fabric_config.management.vpcPeerLinkVlan == "3600" + - replaced_fabric_config.management.vpcAutoRecoveryTimer == 360 + - replaced_fabric_config.management.vpcDelayRestoreTimer == 150 + - replaced_fabric_config.management.advertisePhysicalIp == false + - replaced_fabric_config.management.bgpLoopbackIpRange == "10.2.0.0/22" + - replaced_fabric_config.management.nveLoopbackIpRange == "10.3.0.0/22" + - replaced_fabric_config.management.l2VniRange == "30000-49000" + - replaced_fabric_config.management.l3VniRange == "50000-59000" + fail_msg: >- + Properties not specified in replace task must revert to defaults. + success_msg: "All 15 unspecified properties correctly reverted to defaults" + tags: [test_replaced, test_replaced_validation] + +############################################################################# +# TEST 3: STATE DELETED - Delete fabrics +############################################################################# +- name: "TEST 3a: Delete AI eBGP VXLAN fabric using state deleted" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + register: deleted_result_1 + tags: [test_deleted, test_deleted_delete] + +- name: "TEST 3a: Verify fabric was deleted" + assert: + that: + - deleted_result_1 is changed + - deleted_result_1 is not failed + fail_msg: "AI eBGP VXLAN fabric deletion with state deleted failed" + success_msg: "AI eBGP VXLAN fabric successfully deleted with state deleted" + tags: [test_deleted, test_deleted_delete] + +- name: "TEST 3b: Delete fabric using state deleted (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + register: deleted_result_2 + tags: [test_deleted, test_deleted_idempotent] + +- name: "TEST 3b: Verify deleted state is idempotent" + assert: + that: + - deleted_result_2 is not changed + - deleted_result_2 is not failed + fail_msg: "Deleted state is not idempotent - should not change when deleting non-existent fabric" + success_msg: "Deleted state is idempotent - no changes when deleting non-existent fabric" + tags: [test_deleted, test_deleted_idempotent] + +############################################################################# +# FINAL CLEANUP - Clean up all test fabrics +############################################################################# +- name: "CLEANUP: Delete all AI eBGP VXLAN test fabrics" + cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ebgp_test_fabric_merged }}" + - fabric_name: "{{ ai_ebgp_test_fabric_replaced }}" + ignore_errors: true + tags: [cleanup, always] + +############################################################################# +# TEST SUMMARY +############################################################################# +- name: "TEST SUMMARY: Display test results" + debug: + msg: | + ======================================================== + TEST SUMMARY for cisco.nd.nd_manage_fabric_ai_ebgp_vxlan: + ======================================================== + TEST 1: STATE MERGED + - Create fabric: {{ 'PASSED' if merged_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if merged_result_2 is not changed else 'FAILED' }} + - Update fabric: {{ 'PASSED' if merged_result_3 is changed else 'FAILED' }} + + TEST 2: STATE REPLACED + - Create fabric: {{ 'PASSED' if replaced_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if replaced_result_2 is not changed else 'FAILED' }} + - Replace fabric: {{ 'PASSED' if replaced_result_3 is changed else 'FAILED' }} + + TEST 3: STATE DELETED + - Delete fabric: {{ 'PASSED' if deleted_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if deleted_result_2 is not changed else 'FAILED' }} + ======================================================== diff --git a/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ibgp.yaml b/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ibgp.yaml new file mode 100644 index 00000000..a6d6cd6a --- /dev/null +++ b/tests/integration/targets/nd_manage_fabric/tasks/fabric_ai_ibgp.yaml @@ -0,0 +1,640 @@ +--- +# Test code for the ND modules +# Copyright: (c) 2026, Cisco Systems + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have a Nexus Dashboard host, username and password + ansible.builtin.fail: + msg: 'Please define the following variables: ansible_host, ansible_user and ansible_password.' + when: ansible_host is not defined or ansible_user is not defined or ansible_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + nd_info: &nd_info + output_level: '{{ api_key_output_level | default("debug") }}' + +############################################################################# +# CLEANUP - Ensure clean state before tests +############################################################################# +- name: Clean up any existing test fabrics before starting tests + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ibgp_test_fabric_merged }}" + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + tags: always + +############################################################################# +# TEST 1: STATE MERGED - Create fabric using merged state +############################################################################# +- name: "TEST 1a: Create AI iBGP VXLAN fabric using state merged (first run)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: merged + config: + - "{{ {'fabric_name': ai_ibgp_test_fabric_merged} | combine(fabric_config_ai_ibgp) }}" + register: merged_result_1 + tags: [test_merged, test_merged_create] + +- name: "TEST 1a: Verify fabric was created using merged state" + assert: + that: + - merged_result_1 is changed + - merged_result_1 is not failed + fail_msg: "AI iBGP VXLAN fabric creation with state merged failed" + success_msg: "AI iBGP VXLAN fabric successfully created with state merged" + tags: [test_merged, test_merged_create] + +- name: "TEST 1b: Create fabric using state merged (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: merged + config: + - "{{ {'fabric_name': ai_ibgp_test_fabric_merged} | combine(fabric_config_ai_ibgp) }}" + register: merged_result_2 + tags: [test_merged, test_merged_idempotent] + +- name: "TEST 1b: Verify merged state is idempotent" + assert: + that: + - merged_result_2 is not changed + - merged_result_2 is not failed + fail_msg: "Merged state is not idempotent - should not change when run twice with same config" + success_msg: "Merged state is idempotent - no changes on second run" + tags: [test_merged, test_merged_idempotent] + +- name: "TEST 1c: Update fabric using state merged (modify existing)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: merged + config: + - fabric_name: "{{ ai_ibgp_test_fabric_merged }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65002" # Changed from 65001 + site_id: "65002" # Changed from 65001 + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00bb" # Changed from 00aa + performance_monitoring: true # Changed from false + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 2 + rendezvous_point_loopback_id: 254 + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: loopback + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + advertise_physical_ip: false + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9216 + l2_host_interface_mtu: 9216 + tenant_dhcp: true + nxapi: true + nxapi_https_port: 443 + nxapi_http: false + nxapi_http_port: 80 + snmp_trap: true + anycast_border_gateway_advertise_physical_ip: false + greenfield_debug_flag: enable + tcam_allocation: true + real_time_interface_statistics_collection: false + interface_statistics_load_interval: 10 + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.33.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.5.0.0/22" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + register: merged_result_3 + tags: [test_merged, test_merged_update] + +- name: "TEST 1c: Verify fabric was updated using merged state" + assert: + that: + - merged_result_3 is changed + - merged_result_3 is not failed + fail_msg: "AI iBGP VXLAN fabric update with state merged failed" + success_msg: "AI iBGP VXLAN fabric successfully updated with state merged" + tags: [test_merged, test_merged_update] + +############################################################################# +# VALIDATION: Query ai_ibgp_test_fabric_merged and validate expected changes +############################################################################# +- name: "VALIDATION 1: Authenticate with ND to get token" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/login" + method: POST + headers: + Content-Type: "application/json" + body_format: json + body: + domain: "{{ ansible_httpapi_login_domain | default('local') }}" + userName: "{{ ansible_user }}" + userPasswd: "{{ ansible_password }}" + validate_certs: false + return_content: true + status_code: + - 200 + register: nd_auth_response + tags: [test_merged, test_merged_validation] + delegate_to: localhost + +- name: "VALIDATION 1: Query ai_ibgp_test_fabric_merged configuration from ND" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/api/v1/manage/fabrics/{{ ai_ibgp_test_fabric_merged }}" + method: GET + headers: + Authorization: "Bearer {{ nd_auth_response.json.jwttoken }}" + Content-Type: "application/json" + validate_certs: false + return_content: true + status_code: + - 200 + - 404 + register: merged_fabric_query + tags: [test_merged, test_merged_validation] + delegate_to: localhost + +- name: "VALIDATION 1: Parse fabric configuration response" + set_fact: + merged_fabric_config: "{{ merged_fabric_query.json }}" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1a: Verify fabric type is aimlVxlanIbgp" + assert: + that: + - merged_fabric_config.management.type == "aimlVxlanIbgp" + fail_msg: >- + Fabric type validation failed - expected aimlVxlanIbgp, + got {{ merged_fabric_config.management.type }} + success_msg: "Fabric type correctly set to aimlVxlanIbgp" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1b: Verify changed properties after merge" + assert: + that: + - merged_fabric_config.management.bgpAsn == "65002" + - merged_fabric_config.management.siteId == "65002" + - merged_fabric_config.management.anycastGatewayMac == "2020.0000.00bb" + - merged_fabric_config.management.performanceMonitoring == true + fail_msg: >- + Changed properties validation failed. + bgpAsn: {{ merged_fabric_config.management.bgpAsn }} (expected 65002), + siteId: {{ merged_fabric_config.management.siteId }} (expected 65002), + anycastGatewayMac: {{ merged_fabric_config.management.anycastGatewayMac }} (expected 2020.0000.00bb), + performanceMonitoring: {{ merged_fabric_config.management.performanceMonitoring }} (expected true) + success_msg: "All 4 changed properties updated correctly" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1c: Verify preserved properties (not in merge task)" + assert: + that: + - merged_fabric_config.management.overlayMode == "cli" + - merged_fabric_config.management.underlayIpv6 == false + - merged_fabric_config.management.fabricInterfaceType == "p2p" + - merged_fabric_config.management.linkStateRoutingProtocol == "ospf" + - merged_fabric_config.management.ospfAreaId == "0.0.0.0" + - merged_fabric_config.management.routeReflectorCount == 4 + - merged_fabric_config.management.staticUnderlayIpAllocation == false + fail_msg: >- + Preserved properties validation failed. These fields were not + in the merge task and should retain their original values from creation. + success_msg: "All 7 preserved underlay/overlay properties retained correctly" + tags: [test_merged, test_merged_validation] + +- name: "VALIDATION 1c: Verify preserved banner (not in merge task)" + assert: + that: + - merged_fabric_config.management.banner is defined + - merged_fabric_config.management.banner | length > 0 + - "'ADVISORY' in merged_fabric_config.management.banner" + fail_msg: >- + Banner was reset to empty by the merge operation! + Expected banner containing 'ADVISORY', Actual: '{{ merged_fabric_config.management.banner | default("") }}' + success_msg: "Banner correctly preserved after merge" + tags: [test_merged, test_merged_validation] + +############################################################################# +# TEST 2: STATE REPLACED - Create and manage fabric using replaced state +############################################################################# +- name: "TEST 2a: Create AI iBGP VXLAN fabric using state replaced (first run)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65004" + site_id: "65004" + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00dd" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.3.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 4 + rendezvous_point_loopback_id: 253 + vpc_peer_link_vlan: "3700" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: loopback + vpc_auto_recovery_timer: 300 + vpc_delay_restore_timer: 120 + vpc_peer_link_port_channel_id: "600" + vpc_ipv6_neighbor_discovery_sync: false + advertise_physical_ip: true + vpc_domain_id_range: "1-800" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9000 + l2_host_interface_mtu: 9000 + tenant_dhcp: false + nxapi: false + nxapi_https_port: 443 + nxapi_http: true + nxapi_http_port: 80 + snmp_trap: false + anycast_border_gateway_advertise_physical_ip: true + greenfield_debug_flag: disable + tcam_allocation: false + real_time_interface_statistics_collection: true + interface_statistics_load_interval: 30 + bgp_loopback_ip_range: "10.22.0.0/22" + nve_loopback_ip_range: "10.23.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.252.0/24" + intra_fabric_subnet_range: "10.24.0.0/16" + l2_vni_range: "40000-59000" + l3_vni_range: "60000-69000" + network_vlan_range: "2400-3099" + vrf_vlan_range: "2100-2399" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.53.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.25.0.0/22" + per_vrf_loopback_auto_provision_ipv6: true + per_vrf_loopback_ipv6_range: "fd00::a25:0/112" + banner: "^ AI iBGP Updated via replaced state ^" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + management_ipv6_prefix: 64 + register: replaced_result_1 + tags: [test_replaced, test_replaced_create] + +- name: "TEST 2a: Verify fabric was created using replaced state" + assert: + that: + - replaced_result_1 is changed + - replaced_result_1 is not failed + fail_msg: "AI iBGP VXLAN fabric creation with state replaced failed" + success_msg: "AI iBGP VXLAN fabric successfully created with state replaced" + tags: [test_replaced, test_replaced_create] + +- name: "TEST 2b: Create fabric using state replaced (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65004" + site_id: "65004" + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00dd" + performance_monitoring: true + replication_mode: multicast + multicast_group_subnet: "239.1.3.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 4 + rendezvous_point_loopback_id: 253 + vpc_peer_link_vlan: "3700" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: loopback + vpc_auto_recovery_timer: 300 + vpc_delay_restore_timer: 120 + vpc_peer_link_port_channel_id: "600" + vpc_ipv6_neighbor_discovery_sync: false + advertise_physical_ip: true + vpc_domain_id_range: "1-800" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9000 + l2_host_interface_mtu: 9000 + tenant_dhcp: false + nxapi: false + nxapi_https_port: 443 + nxapi_http: true + nxapi_http_port: 80 + snmp_trap: false + anycast_border_gateway_advertise_physical_ip: true + greenfield_debug_flag: disable + tcam_allocation: false + real_time_interface_statistics_collection: true + interface_statistics_load_interval: 30 + bgp_loopback_ip_range: "10.22.0.0/22" + nve_loopback_ip_range: "10.23.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.252.0/24" + intra_fabric_subnet_range: "10.24.0.0/16" + l2_vni_range: "40000-59000" + l3_vni_range: "60000-69000" + network_vlan_range: "2400-3099" + vrf_vlan_range: "2100-2399" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.53.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.25.0.0/22" + per_vrf_loopback_auto_provision_ipv6: true + per_vrf_loopback_ipv6_range: "fd00::a25:0/112" + banner: "^ AI iBGP Updated via replaced state ^" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + management_ipv6_prefix: 64 + register: replaced_result_2 + tags: [test_replaced, test_replaced_idempotent] + +- name: "TEST 2b: Verify replaced state is idempotent" + assert: + that: + - replaced_result_2 is not changed + - replaced_result_2 is not failed + fail_msg: "Replaced state is not idempotent - should not change when run twice with same config" + success_msg: "Replaced state is idempotent - no changes on second run" + tags: [test_replaced, test_replaced_idempotent] + +- name: "TEST 2c: Update fabric using state replaced (complete replacement with minimal config)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: replaced + config: + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65004" + site_id: "65004" + banner: "^ AI iBGP Updated via replaced state ^" + register: replaced_result_3 + tags: [test_replaced, test_replaced_update] + +- name: "TEST 2c: Verify fabric was completely replaced" + assert: + that: + - replaced_result_3 is changed + - replaced_result_3 is not failed + fail_msg: "AI iBGP VXLAN fabric replacement with state replaced failed" + success_msg: "AI iBGP VXLAN fabric successfully replaced with state replaced" + tags: [test_replaced, test_replaced_update] + +############################################################################# +# VALIDATION: Query ai_ibgp_test_fabric_replaced and validate +############################################################################# +- name: "VALIDATION 2: Authenticate with ND to get token" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/login" + method: POST + headers: + Content-Type: "application/json" + body_format: json + body: + domain: "{{ ansible_httpapi_login_domain | default('local') }}" + userName: "{{ ansible_user }}" + userPasswd: "{{ ansible_password }}" + validate_certs: false + return_content: true + status_code: + - 200 + register: nd_auth_response_2 + tags: [test_replaced, test_replaced_validation] + delegate_to: localhost + +- name: "VALIDATION 2: Query ai_ibgp_test_fabric_replaced configuration from ND" + ansible.builtin.uri: + url: "https://{{ ansible_host }}:{{ ansible_httpapi_port | default(443) }}/api/v1/manage/fabrics/{{ ai_ibgp_test_fabric_replaced }}" + method: GET + headers: + Authorization: "Bearer {{ nd_auth_response_2.json.jwttoken }}" + Content-Type: "application/json" + validate_certs: false + return_content: true + status_code: + - 200 + - 404 + register: replaced_fabric_query + tags: [test_replaced, test_replaced_validation] + delegate_to: localhost + +- name: "VALIDATION 2: Parse fabric configuration response" + set_fact: + replaced_fabric_config: "{{ replaced_fabric_query.json }}" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2a: Verify fabric type is preserved as aimlVxlanIbgp" + assert: + that: + - replaced_fabric_config.management.type == "aimlVxlanIbgp" + fail_msg: >- + Fabric type validation failed after replace - expected aimlVxlanIbgp, + got {{ replaced_fabric_config.management.type }} + success_msg: "Fabric type correctly preserved as aimlVxlanIbgp after replace" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2b: Verify explicitly specified properties in replace" + assert: + that: + - replaced_fabric_config.management.bgpAsn == "65004" + - replaced_fabric_config.management.siteId == "65004" + - replaced_fabric_config.management.banner == "^ AI iBGP Updated via replaced state ^" + fail_msg: >- + Explicitly specified properties validation failed. + success_msg: "All 3 explicitly specified properties set correctly" + tags: [test_replaced, test_replaced_validation] + +- name: "VALIDATION 2c: Verify properties reverted to defaults after replace" + assert: + that: + - replaced_fabric_config.management.anycastGatewayMac == "2020.0000.00aa" + - replaced_fabric_config.management.performanceMonitoring == false + - replaced_fabric_config.management.fabricMtu == 9216 + - replaced_fabric_config.management.l2HostInterfaceMtu == 9216 + - replaced_fabric_config.management.replicationMode == "multicast" + - replaced_fabric_config.management.multicastGroupSubnet == "239.1.1.0/25" + - replaced_fabric_config.management.rendezvousPointCount == 2 + - replaced_fabric_config.management.vpcPeerLinkVlan == "3600" + - replaced_fabric_config.management.vpcAutoRecoveryTimer == 360 + - replaced_fabric_config.management.vpcDelayRestoreTimer == 150 + - replaced_fabric_config.management.advertisePhysicalIp == false + - replaced_fabric_config.management.bgpLoopbackIpRange == "10.2.0.0/22" + - replaced_fabric_config.management.nveLoopbackIpRange == "10.3.0.0/22" + - replaced_fabric_config.management.l2VniRange == "30000-49000" + - replaced_fabric_config.management.l3VniRange == "50000-59000" + fail_msg: >- + Properties not specified in replace task must revert to defaults. + success_msg: "All 15 unspecified properties correctly reverted to defaults" + tags: [test_replaced, test_replaced_validation] + +############################################################################# +# TEST 3: STATE DELETED - Delete fabrics +############################################################################# +- name: "TEST 3a: Delete AI iBGP VXLAN fabric using state deleted" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + register: deleted_result_1 + tags: [test_deleted, test_deleted_delete] + +- name: "TEST 3a: Verify fabric was deleted" + assert: + that: + - deleted_result_1 is changed + - deleted_result_1 is not failed + fail_msg: "AI iBGP VXLAN fabric deletion with state deleted failed" + success_msg: "AI iBGP VXLAN fabric successfully deleted with state deleted" + tags: [test_deleted, test_deleted_delete] + +- name: "TEST 3b: Delete fabric using state deleted (second run - idempotency test)" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + register: deleted_result_2 + tags: [test_deleted, test_deleted_idempotent] + +- name: "TEST 3b: Verify deleted state is idempotent" + assert: + that: + - deleted_result_2 is not changed + - deleted_result_2 is not failed + fail_msg: "Deleted state is not idempotent - should not change when deleting non-existent fabric" + success_msg: "Deleted state is idempotent - no changes when deleting non-existent fabric" + tags: [test_deleted, test_deleted_idempotent] + +############################################################################# +# FINAL CLEANUP - Clean up all test fabrics +############################################################################# +- name: "CLEANUP: Delete all AI iBGP VXLAN test fabrics" + cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + <<: *nd_info + state: deleted + config: + - fabric_name: "{{ ai_ibgp_test_fabric_merged }}" + - fabric_name: "{{ ai_ibgp_test_fabric_replaced }}" + ignore_errors: true + tags: [cleanup, always] + +############################################################################# +# TEST SUMMARY +############################################################################# +- name: "TEST SUMMARY: Display test results" + debug: + msg: | + ======================================================== + TEST SUMMARY for cisco.nd.nd_manage_fabric_ai_ibgp_vxlan: + ======================================================== + TEST 1: STATE MERGED + - Create fabric: {{ 'PASSED' if merged_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if merged_result_2 is not changed else 'FAILED' }} + - Update fabric: {{ 'PASSED' if merged_result_3 is changed else 'FAILED' }} + + TEST 2: STATE REPLACED + - Create fabric: {{ 'PASSED' if replaced_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if replaced_result_2 is not changed else 'FAILED' }} + - Replace fabric: {{ 'PASSED' if replaced_result_3 is changed else 'FAILED' }} + + TEST 3: STATE DELETED + - Delete fabric: {{ 'PASSED' if deleted_result_1 is changed else 'FAILED' }} + - Idempotency: {{ 'PASSED' if deleted_result_2 is not changed else 'FAILED' }} + ======================================================== diff --git a/tests/integration/targets/nd_manage_fabric/tasks/main.yaml b/tests/integration/targets/nd_manage_fabric/tasks/main.yaml index eacc3be3..43c18605 100644 --- a/tests/integration/targets/nd_manage_fabric/tasks/main.yaml +++ b/tests/integration/targets/nd_manage_fabric/tasks/main.yaml @@ -2,6 +2,12 @@ - name: Run nd_manage_fabric iBGP tests ansible.builtin.include_tasks: fabric_ibgp.yaml +- name: Run nd_manage_fabric AI iBGP VXLAN tests + ansible.builtin.include_tasks: fabric_ai_ibgp.yaml + +- name: Run nd_manage_fabric AI eBGP VXLAN tests + ansible.builtin.include_tasks: fabric_ai_ebgp.yaml + - name: Run nd_manage_fabric eBGP tests ansible.builtin.include_tasks: fabric_ebgp.yaml diff --git a/tests/integration/targets/nd_manage_fabric/vars/main.yaml b/tests/integration/targets/nd_manage_fabric/vars/main.yaml index 893b17bb..9d900568 100644 --- a/tests/integration/targets/nd_manage_fabric/vars/main.yaml +++ b/tests/integration/targets/nd_manage_fabric/vars/main.yaml @@ -12,6 +12,14 @@ ext_test_fabric_merged: "ext_test_fabric_merged" ext_test_fabric_replaced: "ext_test_fabric_replaced" ext_test_fabric_deleted: "ext_test_fabric_deleted" +ai_ibgp_test_fabric_merged: "ai_ibgp_test_fabric_merged" +ai_ibgp_test_fabric_replaced: "ai_ibgp_test_fabric_replaced" +ai_ibgp_test_fabric_deleted: "ai_ibgp_test_fabric_deleted" + +ai_ebgp_test_fabric_merged: "ai_ebgp_test_fabric_merged" +ai_ebgp_test_fabric_replaced: "ai_ebgp_test_fabric_replaced" +ai_ebgp_test_fabric_deleted: "ai_ebgp_test_fabric_deleted" + # Common fabric configuration for all tests # common_fabric_config: fabric_config_ibgp: @@ -326,3 +334,278 @@ fabric_config_ebgp: dhcp_end_address: "" management_gateway: "" management_ipv4_prefix: 24 + +# Common AI iBGP VXLAN fabric configuration for all AI iBGP tests +# Uses aimlVxlanIbgp type which shares management properties with vxlanIbgp +fabric_config_ai_ibgp: + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanIbgp + bgp_asn: "65001.55" + site_id: "65001" + overlay_mode: cli + underlay_ipv6: false + fabric_interface_type: p2p + link_state_routing_protocol: ospf + ospf_area_id: "0.0.0.0" + route_reflector_count: 4 + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00aa" + fabric_mtu: 9216 + l2_host_interface_mtu: 9216 + performance_monitoring: false + static_underlay_ip_allocation: false + + # Replication / Multicast + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + tenant_routed_multicast_ipv6: false + rendezvous_point_count: 2 + rendezvous_point_mode: asm + rendezvous_point_loopback_id: 254 + pim_hello_authentication: false + + # vPC + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: loopback + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + vpc_ipv6_neighbor_discovery_sync: true + vpc_layer3_peer_router: true + vpc_tor_delay_restore_timer: 30 + fabric_vpc_domain_id: false + fabric_vpc_qos: false + enable_peer_switch: false + + # PIP / Advertising + advertise_physical_ip: false + advertise_physical_ip_on_border: true + anycast_border_gateway_advertise_physical_ip: false + + # Domain / Loopback IDs + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + + # Templates + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + + # Protocol Authentication + bgp_authentication: false + ospf_authentication: false + bfd: false + macsec: false + vrf_lite_macsec: false + + # BGP / Routing Enhancements + auto_bgp_neighbor_description: true + ibgp_peer_template: "" + leaf_ibgp_peer_template: "" + link_state_routing_tag: "UNDERLAY" + + # Resource ID Ranges + l3_vni_no_vlan_default_option: false + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + sub_interface_dot1q_range: "2-511" + ip_service_level_agreement_id_range: "10000-19999" + object_tracking_number_range: "100-299" + service_network_vlan_range: "3000-3199" + route_map_sequence_number_range: "1-65534" + + # IP Ranges + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + + # VRF Lite / DCI + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.33.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + + # Per-VRF Loopback + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.5.0.0/22" + per_vrf_loopback_auto_provision_ipv6: false + + # Management / System + tenant_dhcp: true + nxapi: true + nxapi_https_port: 443 + nxapi_http: false + nxapi_http_port: 80 + snmp_trap: true + cdp: false + real_time_interface_statistics_collection: false + interface_statistics_load_interval: 10 + tcam_allocation: true + inband_management: false + + # Security + security_group_tag: false + private_vlan: false + + # QoS / Queuing + default_queuing_policy: false + aiml_qos: false + + # DLB / AI + dlb: false + ai_load_sharing: false + + # PTP / STP / MPLS + ptp: false + stp_root_option: unmanaged + mpls_handoff: false + + # Leaf / TOR + allow_vlan_on_leaf_tor_pairing: none + leaf_tor_id_range: false + + # OAM / Compliance + nve_hold_down_timer: 180 + next_generation_oam: true + strict_config_compliance_mode: false + greenfield_debug_flag: enable + + # System Policies + advanced_ssh_option: false + copp_policy: strict + power_redundancy_mode: redundant + host_interface_admin_state: true + policy_based_routing: false + + # Freeform Config + extra_config_leaf: "" + extra_config_spine: "" + extra_config_tor: "" + extra_config_intra_fabric_links: "" + extra_config_aaa: "" + pre_interface_config_leaf: "" + pre_interface_config_spine: "" + pre_interface_config_tor: "" + + # Banner + banner: | + @ADVISORY This is an AI iBGP VXLAN test fabric deployed by Ansible for validation purposes. Do not make changes to this fabric outside of Ansible or use it for production traffic. ADVISORY@ + + # Backup + real_time_backup: false + scheduled_backup: false + + # Brownfield + brownfield_network_name_format: "Auto_Net_VNI$$VNI$$_VLAN$$VLAN_ID$$" + brownfield_skip_overlay_network_attachments: false + + # Hypershield + allow_smart_switch_onboarding: false + + # Bootstrap / DHCP + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24 + +# Common AI eBGP VXLAN fabric configuration for all AI eBGP tests +# Uses aimlVxlanEbgp type which shares management properties with vxlanEbgp +fabric_config_ai_ebgp: + category: fabric + location: + latitude: 37.7749 + longitude: -122.4194 + license_tier: premier + alert_suspend: disabled + security_domain: all + telemetry_collection: false + management: + type: aimlVxlanEbgp + bgp_asn: "65001" + bgp_asn_auto_allocation: false + site_id: "65001" + bgp_as_mode: multiAS + bgp_allow_as_in_num: 1 + bgp_max_path: 4 + auto_configure_ebgp_evpn_peering: true + target_subnet_mask: 30 + anycast_gateway_mac: "2020.0000.00aa" + performance_monitoring: false + replication_mode: multicast + multicast_group_subnet: "239.1.1.0/25" + auto_generate_multicast_group_address: false + underlay_multicast_group_address_limit: 128 + tenant_routed_multicast: false + rendezvous_point_count: 2 + rendezvous_point_loopback_id: 254 + vpc_peer_link_vlan: "3600" + vpc_peer_link_enable_native_vlan: false + vpc_peer_keep_alive_option: management + vpc_auto_recovery_timer: 360 + vpc_delay_restore_timer: 150 + vpc_peer_link_port_channel_id: "500" + advertise_physical_ip: false + vpc_domain_id_range: "1-1000" + bgp_loopback_id: 0 + nve_loopback_id: 1 + vrf_template: Default_VRF_Universal + network_template: Default_Network_Universal + vrf_extension_template: Default_VRF_Extension_Universal + network_extension_template: Default_Network_Extension_Universal + l3_vni_no_vlan_default_option: false + fabric_mtu: 9216 + l2_host_interface_mtu: 9216 + tenant_dhcp: true + nxapi: false + nxapi_https_port: 443 + nxapi_http: false + nxapi_http_port: 80 + snmp_trap: true + anycast_border_gateway_advertise_physical_ip: false + greenfield_debug_flag: disable + tcam_allocation: true + real_time_interface_statistics_collection: false + interface_statistics_load_interval: 10 + bgp_loopback_ip_range: "10.2.0.0/22" + nve_loopback_ip_range: "10.3.0.0/22" + anycast_rendezvous_point_ip_range: "10.254.254.0/24" + intra_fabric_subnet_range: "10.4.0.0/16" + l2_vni_range: "30000-49000" + l3_vni_range: "50000-59000" + network_vlan_range: "2300-2999" + vrf_vlan_range: "2000-2299" + sub_interface_dot1q_range: "2-511" + vrf_lite_auto_config: manual + vrf_lite_subnet_range: "10.33.0.0/16" + vrf_lite_subnet_target_mask: 30 + auto_unique_vrf_lite_ip_prefix: false + per_vrf_loopback_auto_provision: true + per_vrf_loopback_ip_range: "10.5.0.0/22" + banner: "" + day0_bootstrap: false + local_dhcp_server: false + dhcp_protocol_version: dhcpv4 + dhcp_start_address: "" + dhcp_end_address: "" + management_gateway: "" + management_ipv4_prefix: 24