Skip to content

Commit

Permalink
Clean up + add some test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedt committed Sep 27, 2024
1 parent b6609f6 commit a50e00c
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 24 deletions.
4 changes: 2 additions & 2 deletions cisco_aci/datadog_checks/cisco_aci/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,12 +297,12 @@ def get_eth_stats(self, pod, node, eth):
response = self.make_request(path)
return self._parse_response(response)

def get_lldp_adj_ep(self):
def get_lldp_adj_eps(self):
path = '/api/node/class/lldpAdjEp.json'
response = self.make_request(path)
return self._parse_response(response)

def get_cdp_adj_ep(self):
def get_cdp_adj_eps(self):
path = '/api/node/class/cdpAdjEp.json'
response = self.make_request(path)
return self._parse_response(response)
Expand Down
12 changes: 11 additions & 1 deletion cisco_aci/datadog_checks/cisco_aci/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
EPG_REGEX = re.compile('/epg-([^/]+)/')
IP_REGEX = re.compile('/ip-([^/]+)/')
NODE_REGEX = re.compile('node-([0-9]+)')
ETH_REGEX = re.compile('\[([^]]*)\]')
ETH_REGEX = re.compile(r'\[([^]]*)\]')


def parse_capacity_tags(dn):
Expand Down Expand Up @@ -85,6 +85,7 @@ def get_node_from_dn(dn):
"""
return _get_value_from_dn(NODE_REGEX, dn)


def get_eth_id_from_dn(dn):
"""
This parses the interface ID (eth) from a dn designator. They look like this:
Expand All @@ -93,6 +94,15 @@ def get_eth_id_from_dn(dn):
return _get_value_from_dn(ETH_REGEX, dn)


def get_index_from_eth_id(eth_id):
"""
This parses the interface index (eth) from an interface's ID. They look like this:
eth1/49
"""
split = re.split('eth|/', eth_id)
return int(split[-1])


def _get_value_from_dn(regex, dn):
if not dn:
return None
Expand Down
29 changes: 20 additions & 9 deletions cisco_aci/datadog_checks/cisco_aci/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

from . import helpers


"""
Cisco ACI Response Models
"""
Expand Down Expand Up @@ -100,21 +99,31 @@ def local_device_dn(self) -> str:

@computed_field
@property
def remote_device_index(self) -> str:
def local_port_id(self) -> str:
# example: topology/pod-1/paths-201/path-ep-[eth1/1]
# use regex to extract port alias from square brackets - ex: eth1/1
return helpers.get_eth_id_from_dn(self.port_desc)
return helpers.get_eth_id_from_dn(self.dn)

@computed_field
@property
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_port_id(self) -> str:
# example: topology/pod-1/paths-201/path-ep-[eth1/1]
# use regex to extract port alias from square brackets - ex: eth1/1
return helpers.get_eth_id_from_dn(self.dn)
return helpers.get_eth_id_from_dn(self.port_desc)

@computed_field
@property
def remote_port_index(self) -> int:
return helpers.get_index_from_eth_id(self.remote_port_id)


class LldpAdjEp(BaseModel):
attributes: dict = LldpAdjAttributes
attributes: LldpAdjAttributes


"""
Expand Down Expand Up @@ -267,9 +276,9 @@ class SourceType(StrEnum):

class TopologyLinkMetadata(BaseModel):
id: Optional[str] = None
source_type = Optional[SourceType]
local = Optional[TopologyLinkSide]
remote = Optional[TopologyLinkSide]
source_type: Optional[SourceType] = Field(default=None)
local: Optional[TopologyLinkSide] = Field(default=None)
remote: Optional[TopologyLinkSide] = Field(default=None)


class NetworkDevicesMetadata(BaseModel):
Expand All @@ -287,4 +296,6 @@ def append_metadata(self, metadata: DeviceMetadata | InterfaceMetadata):
self.devices.append(metadata)
if isinstance(metadata, InterfaceMetadata):
self.interfaces.append(metadata)
if isinstance(metadata, TopologyLinkMetadata):
self.links.append(metadata)
self.size += 1
25 changes: 13 additions & 12 deletions cisco_aci/datadog_checks/cisco_aci/ndm.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,32 +74,33 @@ def create_topology_link_metadata(lldp_adj_eps, cdp_adj_eps, device_map, namespa
"""
Create a TopologyLinkMetadata object from LLDP or CDP
"""
lldp_adj_eps_list = LldpAdjEp()
for lldp_adj_ep in lldp_adj_eps_list:
for lldp_adj_ep in lldp_adj_eps:
lldp_adj_ep = LldpAdjEp(**lldp_adj_ep.get("lldpAdjEp", {}))

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

remote_entry_unique_id = "{}.{}".format(
lldp_adj_ep.attributes.local_port_index, lldp_adj_ep.attributes.remote_port_index
)

local = TopologyLinkSide(
# TODO: need to grab the device id from mapping
device=TopologyLinkDevice(dd_id=local_device_id),
# TODO: double check resolve the local interface id
interface=TopologyLinkInterface(
dd_id='', id=lldp_adj_ep.attributes.local_port_id, id_type='interface_name'
dd_id=local_interface_id, id=lldp_adj_ep.attributes.local_port_id, id_type='interface_name'
),
)
remote = TopologyLinkSide(
# this is all good afaik
device=TopologyLinkDevice(
name=lldp_adj_ep.attributes.system_name,
description=lldp_adj_ep.attributes.system_desc,
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,
),
# TODO: check on the interface alias/name for resolution vs. taken what's given to us
interface=TopologyLinkInterface(
id=lldp_adj_ep.attributes.remote_port_id,
id_type=lldp_adj_ep.attributes.port_id_t,
id_type="interface_name",
description=lldp_adj_ep.attributes.port_desc,
),
)
Expand All @@ -115,7 +116,7 @@ def get_device_ip_mapping(devices):
devices_map = {}
for device in devices:
key = device.pod_node_id
devices_map[key] = device.ip_address
devices_map[key] = device.id
return devices_map


Expand Down
4 changes: 4 additions & 0 deletions cisco_aci/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,10 @@
# 4efe80304d50330f5ed0f79252ef0a84 - Api.get_apps
'_api_mo_uni_tn_DataDog_json_rsp_subtree_include_stats_no_scoped',
# c8e9a0dbceac67fb1149684f7fc7772c - Api.get_tenant_stats
'_api_node_class_lldpAdjEp_json',
# f3713df3a586908a3a11f4c356153519 - Api.get_lldp_adj_eps
'_api_node_class_cdpAdjEp_json',
# 588ea77fffc6df4b37dfdfa4290cdc89 - Api.get_cdp_adj_eps
]

# The map will contain the md5 hash to the fixture
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"totalCount": "0",
"imdata": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"totalCount": "1",
"imdata": [
{
"lldpAdjEp": {
"attributes": {
"capability": "router",
"chassisIdT": "mac",
"chassisIdV": "6a:00:21:1f:55:2a",
"childAction": "",
"dn": "topology/pod-1/node-101/sys/lldp/inst/if-[eth1/49]/adj-1",
"enCap": "",
"id": "1",
"mgmtId": "0",
"mgmtIp": "10.0.200.5",
"mgmtPortMac": "unspecified",
"modTs": "2024-09-12T06:51:52.580+00:00",
"monPolDn": "uni/fabric/monfab-default",
"name": "",
"portDesc": "topology/pod-1/paths-201/pathep-[eth5/1]",
"portIdT": "mac",
"portIdV": "6a:00:21:1f:55:2a",
"portVlan": "unspecified",
"stQual": "",
"status": "",
"sysDesc": "topology/pod-1/node-201",
"sysName": "SP201",
"ttl": "120"
}
}
},
{
"lldpAdjEp": {
"attributes": {
"capability": "router",
"chassisIdT": "mac",
"chassisIdV": "6a:00:21:1f:55:2b",
"childAction": "",
"dn": "topology/pod-1/node-102/sys/lldp/inst/if-[eth1/49]/adj-1",
"enCap": "",
"id": "1",
"mgmtId": "0",
"mgmtIp": "10.0.200.5",
"mgmtPortMac": "unspecified",
"modTs": "2024-09-12T06:51:52.580+00:00",
"monPolDn": "uni/fabric/monfab-default",
"name": "",
"portDesc": "topology/pod-1/paths-201/pathep-[eth5/2]",
"portIdT": "mac",
"portIdV": "6a:00:21:1f:55:2b",
"portVlan": "unspecified",
"stQual": "",
"status": "",
"sysDesc": "topology/pod-1/node-201",
"sysName": "SP201",
"ttl": "120"
}
}
}
]
}
60 changes: 60 additions & 0 deletions cisco_aci/tests/fixtures/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3191,6 +3191,65 @@
},
]

TOPOLOGY_LINK_METADATA = [
{
'id': 'default:10.0.200.0:49.1',
'local': {
'device': {
'dd_id': 'default:10.0.200.0',
},
'interface': {
'dd_id': 'default:10.0.200.0:49',
'id': 'eth1/49',
'id_type': 'interface_name',
},
},
'remote': {
'device': {
'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': {
'description': 'topology/pod-1/paths-201/pathep-[eth5/1]',
'id': 'eth5/1',
'id_type': 'interface_name',
},
},
'source_type': 'lldp',
},
{
'id': 'default:10.0.200.1:49.2',
'local': {
'device': {
'dd_id': 'default:10.0.200.1',
},
'interface': {
'dd_id': 'default:10.0.200.1:49',
'id': 'eth1/49',
'id_type': 'interface_name',
},
},
'remote': {
'device': {
'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': {
'description': 'topology/pod-1/paths-201/pathep-[eth5/2]',
'id': 'eth5/2',
'id_type': 'interface_name',
},
},
'source_type': 'lldp',
},
]

EXPECTED_DEVICE_METADATA_RESULT = DeviceMetadataList(device_metadata=DEVICE_METADATA)

# "2012-01-14 03:21:34" in seconds
Expand All @@ -3211,6 +3270,7 @@
NetworkDevicesMetadata(
namespace='default',
interfaces=INTERFACE_METADATA[193::],
links=TOPOLOGY_LINK_METADATA,
collect_timestamp=MOCK_TIME_EPOCH,
),
]

0 comments on commit a50e00c

Please sign in to comment.