Skip to content

Commit

Permalink
Merge branch 'develop' into relative-imports
Browse files Browse the repository at this point in the history
  • Loading branch information
allenrobel authored Nov 20, 2024
2 parents 1b7c167 + dd6179c commit 867b73d
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 1 deletion.
34 changes: 34 additions & 0 deletions plugins/module_utils/fabric/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,38 @@ def _set_fabric_create_endpoint(self, payload):
self.path = self.ep_fabric_create.path
self.verb = self.ep_fabric_create.verb

def _add_ext_fabric_type_to_payload(self, payload: dict) -> dict:
"""
# Summary
If the payload contains an external fabric type (e.g ISN)
and does not contain the EXT_FABRIC_TYPE key, add this
key with the default value that NDFC GUI uses for displaying
the fabric type.
# Raises
None
"""
method_name = inspect.stack()[0][3]

fabric_type = payload.get("FABRIC_TYPE")
if fabric_type not in self.fabric_types.external_fabric_types:
return payload
if "EXT_FABRIC_TYPE" in payload:
return payload
value = self.fabric_types.fabric_type_to_ext_fabric_type_map.get(fabric_type)
if value is None:
return payload
payload["EXT_FABRIC_TYPE"] = value

msg = f"{self.class_name}.{method_name}: "
msg += "Added EXT_FABRIC_TYPE to payload. "
msg += f"fabric_type: {fabric_type}, "
msg += f"value: {value}"
self.log.debug(msg)
return payload

def _send_payloads(self):
"""
- If ``check_mode`` is ``False``, send the payloads
Expand All @@ -123,6 +155,8 @@ def _send_payloads(self):
- This overrides the parent class method.
"""
for payload in self._payloads_to_commit:
payload = self._add_ext_fabric_type_to_payload(payload)

try:
self._set_fabric_create_endpoint(payload)
except ValueError as error:
Expand Down
46 changes: 46 additions & 0 deletions plugins/module_utils/fabric/fabric_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,28 @@ def _init_fabric_types(self) -> None:
self._fabric_type_to_feature_name_map["VXLAN_EVPN"] = "vxlan"
self._fabric_type_to_feature_name_map["VXLAN_EVPN_MSD"] = "vxlan"

# Map fabric type to the value that the controller GUI displays
# in the Fabric Type column at NDFC -> Manage -> Fabrics
# This is needed only for fabrics that use the External_Fabric
# template, e.g. ISN, and will be inserted into the POST request
# payload for external fabrics as (in the case of ISN fabric type):
# "EXT_FABRIC_TYPE": "Multi-Site External Network"
#
# Exposed via property fabric_type_to_ext_fabric_type_map
self._fabric_type_to_ext_fabric_type_map = {}
self._fabric_type_to_ext_fabric_type_map["ISN"] = "Multi-Site External Network"

self._valid_fabric_types = sorted(self._fabric_type_to_template_name_map.keys())

# self._external_fabric_types is used in conjunction with
# self._fabric_type_to_ext_fabric_type_map. This is used in (at least)
# FabricCreateCommon() to determine if EXT_FABRIC_TYPE key needs to be
# added to a payload.
#
# Exposed via property external_fabric_types
self._external_fabric_types = set()
self._external_fabric_types.add("ISN")

self._mandatory_parameters_all_fabrics = []
self._mandatory_parameters_all_fabrics.append("FABRIC_NAME")
self._mandatory_parameters_all_fabrics.append("FABRIC_TYPE")
Expand Down Expand Up @@ -128,6 +148,19 @@ def _init_properties(self) -> None:
self._properties["template_name"] = None
self._properties["valid_fabric_types"] = self._valid_fabric_types

@property
def external_fabric_types(self):
"""
# Summary
set() containing all external fabric types e.g. ISN.
# Raises
None
"""
return self._external_fabric_types

@property
def fabric_type(self):
"""
Expand All @@ -150,6 +183,19 @@ def fabric_type(self, value):
raise ValueError(msg)
self._properties["fabric_type"] = value

@property
def fabric_type_to_ext_fabric_type_map(self):
"""
# Summary
Returns a dictionary, keyed on fabric_type (e.g. "ISN"),
whose value is a string that the NDFC GUI uses to describe the
external fabric type. See the Fabric Type column at
NDFC -> Manage -> Fabrics for an example of how this is used
by the NDFC GUI.
"""
return self._fabric_type_to_ext_fabric_type_map

@property
def feature_name(self):
"""
Expand Down
21 changes: 21 additions & 0 deletions plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"VPC_PAIR_DELETE_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair?serialNumber={}",
"VPC_PAIR_DEPLOY_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-deploy/{}?forceShowRun=false",
"VPC_PAIR_CFG_SAVE_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-save",
"VPC_PEER_LINK_GET_PATH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair/recommendation?serialNumber={}&useVirtualPeerlink=true",
"FABRIC_ACCESS_MODE": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/accessmode",
},
}
Expand Down Expand Up @@ -209,6 +210,22 @@ def dcnm_vpc_pair_utils_get_vpc_pair_info_from_dcnm(self, swid):
else:
return []

# Get useVirtualPeerlink information
path = self.paths["VPC_PEER_LINK_GET_PATH"]
path = path.format(peerOneId)

resp = dcnm_send(self.module, "GET", path)

if (
resp
and (resp["RETURN_CODE"] == 200)
and (resp["MESSAGE"] == "OK")
and resp["DATA"]
):
useVirtualPeerlink = resp["DATA"][0].get("useVirtualPeerlink", None)
else:
return []

# Get the Profile information now and combine both the first response data and the current one to
# form the 'have' object. There is no direct call to get this combined information.
path = self.paths["VPC_PAIR_GET_POLICY_PATH"]
Expand All @@ -226,6 +243,7 @@ def dcnm_vpc_pair_utils_get_vpc_pair_info_from_dcnm(self, swid):
resp["DATA"]["peerTwoId"] = peerTwoId
resp["DATA"]["peerOneDbId"] = peerOneDbId
resp["DATA"]["peerTwoDbId"] = peerTwoDbId
resp["DATA"]["useVirtualPeerlink"] = useVirtualPeerlink

# Some of the fields in 'have' may be different than what is sent in CREATE/UPDATE/DELETE payloads to DCNM. Update these
# fields,if any, so that all keys are consistent between 'want' and 'have'. This will be necessary for compare function to
Expand Down Expand Up @@ -634,6 +652,9 @@ def dcnm_vpc_pair_utils_process_modify_payloads(self):
path = self.paths["VPC_PAIR_UPDATE_PATH"]

json_payload = json.dumps(elem)
# Sample json_payload
# '{"useVirtualPeerlink":true,"peerOneId":"FDO24020JMB","peerTwoId":"FDO24020JMT"}'

resp = dcnm_send(self.module, "PUT", path, json_payload)

if resp != []:
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/dcnm_vpc_pair.py
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ def dcnm_vpc_pair_validate_input(self, cfg):
"peerOneId": {"required": "True", "type": "ipv4"},
"peerTwoId": {"required": "True", "type": "ipv4"},
"templateName": {"type": "str"},
"useVirtualPeerLink": {"type": "bool"},
"useVirtualPeerlink": {"type": "bool"},
"profile": {"type": "dict"},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,32 @@
}
},

"vpc_pair_info_virtual_peer_link_resp":
{
"DATA": [{
"blockSelection": "False",
"currentPeer": "True",
"ethSwitchId": 178800,
"fabricName": "None",
"ipAddress": "172.31.217.103",
"lanId": 0,
"logicalName": "93180YC-FX3S-L1-S1",
"nxosVersion": "10.4(3)",
"platformType": "None",
"recommendationReason": "Switches have same role and support Virtual Fabric Peering",
"recommended": "True",
"serialNumber": "FDO24020JMT",
"useVirtualPeerlink": "False",
"uuid": "None",
"vdcId": 0,
"vdcName": "None"
}],
"MESSAGE": "OK",
"METHOD": "GET",
"REQUEST_PATH": "https://10.78.210.227:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/vpcpair/recommendation?serialNumber=FDO24020JMB&useVirtualPeerlink=true",
"RETURN_CODE": 200
},

"vpc_pair_policy_resp_84":
{
"RETURN_CODE": 200,
Expand Down
Loading

0 comments on commit 867b73d

Please sign in to comment.