Skip to content

Commit

Permalink
Add local resolution, utilize interface raw ID
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedt committed Dec 3, 2024
1 parent 1674a4b commit 9523c73
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 28 deletions.
24 changes: 24 additions & 0 deletions cisco_aci/datadog_checks/cisco_aci/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ class LldpAdjAttributes(BaseModel):
sys_desc: Optional[str] = Field(default=None, alias="sysDesc")
sys_name: Optional[str] = Field(default=None, alias="sysName")

@computed_field
@property
def ndm_remote_interface_type(self) -> str:
# map the Cisco ACI port subtype to match what NDM (writer) expects
port_subtype_mapping = {
"if-alias": "interface_alias",
"port-name": "interface_name",
"mac": "mac_address",
"nw-addr": "network_address",
"if-name": "interface_name",
"agent-ckt-id": "agent_circuit_id",
"local": "local",
}
if self.port_id_t:
return port_subtype_mapping.get(self.port_id_t, "unknown")
return "unknown"

@computed_field
@property
def local_device_dn(self) -> str:
Expand All @@ -109,6 +126,13 @@ def local_port_id(self) -> str:
def local_port_index(self) -> int:
return helpers.get_index_from_eth_id(self.local_port_id)

@computed_field
@property
def remote_device_dn(self) -> str:
# example: topology/pod-1/paths-201/path-ep-[eth1/1]
# use regex to extract the pod/node - ex: pod-1-node-201
return helpers.get_hostname_from_dn(self.sys_desc)

@computed_field
@property
def remote_port_id(self) -> str:
Expand Down
79 changes: 57 additions & 22 deletions cisco_aci/datadog_checks/cisco_aci/ndm.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,52 +74,87 @@ def create_interface_metadata(phys_if, address, namespace):

def create_topology_link_metadata(lldp_adj_eps, cdp_adj_eps, device_map, namespace):
"""
Create a TopologyLinkMetadata object from LLDP or CDP
Create a TopologyLinkMetadata object from LLDP or CDP (only LLDP is supported as of right now)
"""
for lldp_adj_ep in lldp_adj_eps:
lldp_adj_ep = LldpAdjEp(**lldp_adj_ep.get("lldpAdjEp", {}))
lldp_attrs = lldp_adj_ep.attributes

local_device_id = device_map.get(lldp_adj_ep.attributes.local_device_dn)
local_interface_id = "{}:{}".format(local_device_id, lldp_adj_ep.attributes.local_port_id)

remote_entry_unique_id = "{}.{}".format(
lldp_adj_ep.attributes.local_port_index, lldp_adj_ep.attributes.remote_port_index
)
local_device_id = device_map.get(lldp_attrs.local_device_dn)
local_interface_id = "{}:{}".format(local_device_id, lldp_attrs.local_port_id)

local = TopologyLinkSide(
device=TopologyLinkDevice(dd_id=local_device_id),
interface=TopologyLinkInterface(
dd_id=local_interface_id, id=lldp_adj_ep.attributes.local_port_id, id_type='interface_name'
dd_id=local_interface_id, id=lldp_attrs.local_port_id, id_type='interface_name'
),
)

remote_device_dd_id = get_remote_device_dd_id(device_map, lldp_attrs.remote_device_dn, lldp_attrs.mgmt_ip)
remote_device = TopologyLinkDevice(
name=lldp_attrs.sys_name,
description=lldp_attrs.sys_desc,
id=lldp_attrs.chassis_id_v,
id_type=lldp_attrs.chassis_id_t,
ip_address=lldp_attrs.mgmt_ip,
)
if remote_device_dd_id:
remote_device.dd_id = remote_device_dd_id
remote_interface = TopologyLinkInterface(
id=lldp_attrs.port_id_v,
id_type=lldp_attrs.ndm_remote_interface_type,
description=lldp_attrs.port_desc,
)
if remote_device_dd_id:
remote_interface.dd_id = get_interface_dd_id(remote_device_dd_id, lldp_attrs.remote_port_id)

remote = TopologyLinkSide(
device=TopologyLinkDevice(
name=lldp_adj_ep.attributes.sys_name,
description=lldp_adj_ep.attributes.sys_desc,
id=lldp_adj_ep.attributes.chassis_id_v,
id_type=lldp_adj_ep.attributes.chassis_id_t,
ip_address=lldp_adj_ep.attributes.mgmt_ip,
),
interface=TopologyLinkInterface(
id=lldp_adj_ep.attributes.remote_port_id,
id_type="interface_name",
description=lldp_adj_ep.attributes.port_desc,
),
device=remote_device,
interface=remote_interface,
)

if remote_device_dd_id:
link_id = (
f"{local_device_id}:{get_raw_id(lldp_attrs.local_port_id)}.{get_raw_id(lldp_attrs.remote_port_id)}"
)
else:
link_id = f"{local_device_id}:{get_raw_id(lldp_attrs.local_port_id)}.{lldp_attrs.remote_port_index}"

yield TopologyLinkMetadata(
id='{}:{}'.format(local_device_id, remote_entry_unique_id),
id=link_id,
source_type=SourceType.LLDP,
local=local,
remote=remote,
)


def get_remote_device_dd_id(device_map, remote_device_dn, mgmt_ip) -> str | None:
"""
Get the Cisco DN for a remote device, if the device is in the device map then
check that it matches the management IP of the LLDP neighbor, then return it
"""
device_id = device_map.get(remote_device_dn, "")
if device_id:
if device_id.endswith(mgmt_ip):
return device_id
return None


def get_interface_dd_id(device_id: str, port_id: str) -> str:
"""
Create the interface DD ID based off of the device DD ID and port ID
ex: default:10.0.200.1:cisco_aci-eth1/1
"""
return '{}:cisco_aci-{}'.format(device_id, port_id)
raw_id = get_raw_id(port_id)
return f"{device_id}:{raw_id}"


def get_raw_id(raw_id, raw_id_type="cisco-aci") -> str:
"""
Create the interface raw ID, based on the type (cisco-aci) and the interface's identifier
separated by a hyphen - ex: cisco-aci-eth1/1
"""
return f"{raw_id_type}-{raw_id}"


def get_device_ip_mapping(devices):
Expand Down
16 changes: 10 additions & 6 deletions cisco_aci/tests/fixtures/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@

TOPOLOGY_LINK_METADATA = [
{
'id': 'default:10.0.200.0:49.1',
'id': 'default:10.0.200.0:cisco-aci-eth1/49.cisco-aci-eth5/1',
'local': {
'device': {
'dd_id': 'default:10.0.200.0',
Expand All @@ -287,22 +287,24 @@
},
'remote': {
'device': {
'dd_id': 'default:10.0.200.5',
'description': 'topology/pod-1/node-201',
'id': '6a:00:21:1f:55:2a',
'id_type': 'mac',
'ip_address': '10.0.200.5',
'name': 'SP201',
},
'interface': {
'dd_id': 'default:10.0.200.5:cisco-aci-eth5/1',
'description': 'topology/pod-1/paths-201/pathep-[eth5/1]',
'id': 'eth5/1',
'id_type': 'interface_name',
'id': '6a:00:21:1f:55:2a',
'id_type': 'mac_address',
},
},
'source_type': 'lldp',
},
{
'id': 'default:10.0.200.1:49.2',
'id': 'default:10.0.200.1:cisco-aci-eth1/49.cisco-aci-eth5/2',
'local': {
'device': {
'dd_id': 'default:10.0.200.1',
Expand All @@ -315,16 +317,18 @@
},
'remote': {
'device': {
'dd_id': 'default:10.0.200.5',
'description': 'topology/pod-1/node-201',
'id': '6a:00:21:1f:55:2b',
'id_type': 'mac',
'ip_address': '10.0.200.5',
'name': 'SP201',
},
'interface': {
'dd_id': 'default:10.0.200.5:cisco-aci-eth5/2',
'description': 'topology/pod-1/paths-201/pathep-[eth5/2]',
'id': 'eth5/2',
'id_type': 'interface_name',
'id': '6a:00:21:1f:55:2b',
'id_type': 'mac_address',
},
},
'source_type': 'lldp',
Expand Down

0 comments on commit 9523c73

Please sign in to comment.