Skip to content

Commit e33016a

Browse files
authored
Merge branch 'develop' into dependabot/pip/types-pyyaml-6.0.12.20240808
2 parents ac10c91 + 710398b commit e33016a

File tree

24 files changed

+558
-58
lines changed

24 files changed

+558
-58
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ docs/_static/
5959
.venv
6060
.vscode
6161
.devcontainer
62+
.python-version
6263

6364
env
6465
*.swp

docs/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
urllib3==2.2.1 # https://github.com/readthedocs/readthedocs.org/issues/10290
1+
urllib3==2.2.2 # https://github.com/readthedocs/readthedocs.org/issues/10290
22
sphinx==7.3.7
33
sphinx-rtd-theme==2.0.0
44
invoke==2.2.0
55
jinja2==3.1.4
66
MarkupSafe==2.1.5
7-
pytest==8.2.1
8-
ansible==9.6.0
7+
pytest==8.3.2
8+
ansible==9.6.1

napalm/base/base.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,12 +921,23 @@ def get_ntp_servers(self) -> Dict[str, models.NTPServerDict]:
921921
"""
922922
Returns the NTP servers configuration as dictionary.
923923
The keys of the dictionary represent the IP Addresses of the servers.
924-
Inner dictionaries do not have yet any available keys.
924+
Inner dictionaries MAY contain information regarding per-server configuration.
925925
926926
Example::
927927
928928
{
929-
'192.168.0.1': {},
929+
'192.168.0.1':
930+
{
931+
'address': '192.168.0.1',
932+
'port': 123,
933+
'version': 4,
934+
'association_type': 'SERVER',
935+
'iburst': False,
936+
'prefer': False,
937+
'network_instance': 'default',
938+
'source_address': '192.0.2.1',
939+
'key_id': -1,
940+
},
930941
'17.72.148.53': {},
931942
'37.187.56.220': {},
932943
'162.158.20.18': {}

napalm/base/models.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,22 @@
223223

224224
NTPPeerDict = TypedDict(
225225
"NTPPeerDict",
226-
{
227-
# will populate it in the future wit potential keys
228-
},
226+
{},
229227
total=False,
230228
)
231229

232230
NTPServerDict = TypedDict(
233231
"NTPServerDict",
234232
{
235-
# will populate it in the future wit potential keys
233+
"address": str,
234+
"port": int,
235+
"version": int,
236+
"association_type": str,
237+
"iburst": bool,
238+
"prefer": bool,
239+
"network_instance": str,
240+
"source_address": str,
241+
"key_id": int,
236242
},
237243
total=False,
238244
)

napalm/base/test/getters.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,9 @@ def test_get_ntp_peers(self, test_case):
311311

312312
for peer, peer_details in get_ntp_peers.items():
313313
assert isinstance(peer, str)
314-
assert helpers.test_model(models.NTPPeerDict, peer_details)
314+
assert helpers.test_model(
315+
models.NTPPeerDict, peer_details, allow_subset=True
316+
)
315317

316318
return get_ntp_peers
317319

@@ -323,7 +325,9 @@ def test_get_ntp_servers(self, test_case):
323325

324326
for server, server_details in get_ntp_servers.items():
325327
assert isinstance(server, str)
326-
assert helpers.test_model(models.NTPServerDict, server_details)
328+
assert helpers.test_model(
329+
models.NTPServerDict, server_details, allow_subset=True
330+
)
327331

328332
return get_ntp_servers
329333

napalm/base/test/helpers.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
"""Several methods to help with the tests."""
22

33

4-
def test_model(model, data):
4+
def test_model(model, data, allow_subset=False):
55
"""Return if the dictionary `data` complies with the `model`."""
66
# Access the underlying schema for a TypedDict directly
7-
model = model.__annotations__
8-
same_keys = set(model.keys()) == set(data.keys())
7+
annotations = model.__annotations__
8+
if allow_subset:
9+
same_keys = set(data.keys()) <= set(annotations.keys())
10+
source = data
11+
else:
12+
same_keys = set(annotations.keys()) == set(data.keys())
13+
source = annotations
914

1015
if not same_keys:
1116
print(
1217
"model_keys: {}\ndata_keys: {}".format(
13-
sorted(model.keys()), sorted(data.keys())
18+
sorted(annotations.keys()), sorted(data.keys())
1419
)
1520
)
1621

1722
correct_class = True
18-
for key, instance_class in model.items():
19-
correct_class = isinstance(data[key], instance_class) and correct_class
23+
for key in source.keys():
24+
correct_class = isinstance(data[key], annotations[key]) and correct_class
2025
if not correct_class:
2126
print(
2227
"key: {}\nmodel_class: {}\ndata_class: {}".format(
23-
key, instance_class, data[key].__class__
28+
key, annotations[key], data[key].__class__
2429
)
2530
)
2631

napalm/eos/eos.py

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,21 +1202,78 @@ def get_arp_table(self, vrf=""):
12021202
return arp_table
12031203

12041204
def get_ntp_servers(self):
1205-
commands = ["show running-config | section ntp"]
1205+
result = {}
12061206

1207-
raw_ntp_config = self._run_commands(commands, encoding="text")[0].get(
1208-
"output", ""
1209-
)
1207+
commands = ["show running-config | section ntp"]
12101208

1211-
ntp_config = napalm.base.helpers.textfsm_extractor(
1212-
self, "ntp_peers", raw_ntp_config
1209+
raw_ntp_config = (
1210+
self._run_commands(commands, encoding="text")[0]
1211+
.get("output", "")
1212+
.splitlines()
12131213
)
12141214

1215-
return {
1216-
str(ntp_peer.get("ntppeer")): {}
1217-
for ntp_peer in ntp_config
1218-
if ntp_peer.get("ntppeer", "")
1219-
}
1215+
for server in raw_ntp_config:
1216+
details = {
1217+
"port": 123,
1218+
"version": 4,
1219+
"association_type": "SERVER",
1220+
"iburst": False,
1221+
"prefer": False,
1222+
"network_instance": "default",
1223+
"source_address": "",
1224+
"key_id": -1,
1225+
}
1226+
tokens = server.split()
1227+
if tokens[2] == "vrf":
1228+
details["network_instance"] = tokens[3]
1229+
server_ip = details["address"] = tokens[4]
1230+
idx = 5
1231+
else:
1232+
server_ip = details["address"] = tokens[2]
1233+
idx = 3
1234+
try:
1235+
parsed_address = napalm.base.helpers.ipaddress.ip_address(server_ip)
1236+
family = parsed_address.version
1237+
except ValueError:
1238+
# Assume family of 4, unless local-interface has no IPv4 addresses
1239+
family = 4
1240+
while idx < len(tokens):
1241+
if tokens[idx] == "iburst":
1242+
details["iburst"] = True
1243+
idx += 1
1244+
1245+
elif tokens[idx] == "key":
1246+
details["key_id"] = int(tokens[idx + 1])
1247+
idx += 2
1248+
1249+
elif tokens[idx] == "local-interface":
1250+
interfaces = self.get_interfaces_ip()
1251+
intf = tokens[idx + 1]
1252+
if family == 6 and interfaces[intf]["ipv6"]:
1253+
details["source_address"] = list(
1254+
interfaces[intf]["ipv6"].keys()
1255+
)[0]
1256+
elif interfaces[intf]["ipv4"]:
1257+
details["source_address"] = list(
1258+
interfaces[intf]["ipv4"].keys()
1259+
)[0]
1260+
elif interfaces[intf]["ipv6"]:
1261+
details["source_address"] = list(
1262+
interfaces[intf]["ipv6"].keys()
1263+
)[0]
1264+
idx += 2
1265+
1266+
elif tokens[idx] == "version":
1267+
details["version"] = int(tokens[idx + 1])
1268+
idx += 2
1269+
1270+
elif tokens[idx] == "prefer":
1271+
details["prefer"] = True
1272+
idx += 1
1273+
1274+
result[server_ip] = details
1275+
1276+
return result
12201277

12211278
def get_ntp_stats(self):
12221279
ntp_stats = []
@@ -1687,7 +1744,7 @@ def traceroute(
16871744
commands = []
16881745

16891746
if vrf:
1690-
commands.append("routing-context vrf {vrf}".format(vrf=vrf))
1747+
commands.append("cli vrf {vrf}".format(vrf=vrf))
16911748

16921749
if source:
16931750
source_opt = "-s {source}".format(source=source)
@@ -2193,7 +2250,7 @@ def ping(
21932250
commands = []
21942251

21952252
if vrf:
2196-
commands.append("routing-context vrf {vrf}".format(vrf=vrf))
2253+
commands.append("cli vrf {vrf}".format(vrf=vrf))
21972254

21982255
command = "ping {}".format(destination)
21992256
command += " timeout {}".format(timeout)

napalm/eos/utils/textfsm_templates/ntp_peers.tpl

Lines changed: 0 additions & 6 deletions
This file was deleted.

napalm/ios/ios.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import telnetlib
2323
import tempfile
2424
import uuid
25-
from collections import defaultdict
2625

2726
from netmiko import FileTransfer, InLineTransfer
2827

@@ -2076,7 +2075,7 @@ def get_bgp_neighbors(self):
20762075
return bgp_neighbor_data
20772076

20782077
def get_bgp_neighbors_detail(self, neighbor_address=""):
2079-
bgp_detail = defaultdict(lambda: defaultdict(lambda: []))
2078+
bgp_detail = {}
20802079

20812080
raw_bgp_sum = self._send_command("show ip bgp all sum").strip()
20822081

@@ -2227,6 +2226,14 @@ def get_bgp_neighbors_detail(self, neighbor_address=""):
22272226
"export_policy": bgp_neigh_afi["policy_out"],
22282227
}
22292228
)
2229+
2230+
vrf_name = details["routing_table"]
2231+
if vrf_name not in bgp_detail.keys():
2232+
bgp_detail[vrf_name] = {}
2233+
remote_as = details["remote_as"]
2234+
if remote_as not in bgp_detail[vrf_name].keys():
2235+
bgp_detail[vrf_name][remote_as] = []
2236+
22302237
bgp_detail[details["routing_table"]][details["remote_as"]].append(details)
22312238
return bgp_detail
22322239

napalm/nxos/nxos.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,27 +1204,32 @@ def get_arp_table(self, vrf: str = "") -> List[models.ARPTableDict]:
12041204
)
12051205
return arp_table
12061206

1207-
def _get_ntp_entity(
1208-
self, peer_type: str
1209-
) -> Dict[str, Union[models.NTPPeerDict, models.NTPServerDict]]:
1210-
ntp_entities: Dict[str, Union[models.NTPPeerDict, models.NTPServerDict]] = {}
1207+
def _filter_ntp_table(self, peer_type: str) -> List[str]:
1208+
ret = []
12111209
command = "show ntp peers"
12121210
ntp_peers_table = self._get_command_table(command, "TABLE_peers", "ROW_peers")
1213-
12141211
for ntp_peer in ntp_peers_table:
12151212
if ntp_peer.get("serv_peer", "").strip() != peer_type:
12161213
continue
12171214
peer_addr = napalm.base.helpers.ip(ntp_peer.get("PeerIPAddress").strip())
1218-
# Ignore the type of the following line until NTP data is modelled
1219-
ntp_entities[peer_addr] = {} # type: ignore
1220-
1221-
return ntp_entities
1215+
ret.append(peer_addr)
1216+
return ret
12221217

12231218
def get_ntp_peers(self) -> Dict[str, models.NTPPeerDict]:
1224-
return self._get_ntp_entity("Peer")
1219+
ntp_entities: Dict[str, models.NTPPeerDict] = {}
1220+
peers = self._filter_ntp_table("Peer")
1221+
for peer_addr in peers:
1222+
ntp_entities[peer_addr] = {}
1223+
1224+
return ntp_entities
12251225

12261226
def get_ntp_servers(self) -> Dict[str, models.NTPServerDict]:
1227-
return self._get_ntp_entity("Server")
1227+
ntp_entities: Dict[str, models.NTPServerDict] = {}
1228+
peers = self._filter_ntp_table("Server")
1229+
for peer_addr in peers:
1230+
ntp_entities[peer_addr] = {}
1231+
1232+
return ntp_entities
12281233

12291234
def get_ntp_stats(self) -> List[models.NTPStats]:
12301235
ntp_stats: List[models.NTPStats] = []

0 commit comments

Comments
 (0)