Skip to content

Commit 5edf95e

Browse files
committed
test: add test for ntp client
1 parent d6508a7 commit 5edf95e

File tree

10 files changed

+254
-4
lines changed

10 files changed

+254
-4
lines changed

test/case/ietf_system/Readme.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ include::timezone_utc_offset/Readme.adoc[]
1616
include::ssh_key_authentication/Readme.adoc[]
1717

1818
include::upgrade/Readme.adoc[]
19+
20+
include::ntp_client/Readme.adoc[]

test/case/ietf_system/ietf_system.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@
1616

1717
- name: ssh_key_authentication
1818
case: ssh_key_authentication/test.py
19+
20+
- name: ntp_client
21+
case: ntp_client/test.py
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== Simple NTP client test
2+
==== Description
3+
Verify NTP client to multiple NTP servers and verify that one get selected
4+
5+
==== Topology
6+
ifdef::topdoc[]
7+
image::../../test/case/ietf_system/ntp_client/topology.svg[Simple NTP client test topology]
8+
endif::topdoc[]
9+
ifndef::topdoc[]
10+
ifdef::testgroup[]
11+
image::ntp_client/topology.svg[Simple NTP client test topology]
12+
endif::testgroup[]
13+
ifndef::testgroup[]
14+
image::topology.svg[Simple NTP client test topology]
15+
endif::testgroup[]
16+
endif::topdoc[]
17+
==== Test sequence
18+
. Set up topology and attach to target DUT
19+
. Configure NTP client on 'target'
20+
. Verify one source is in 'selected' state on 'target'
21+
22+
23+
<<<
24+
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Simple NTP client test
4+
5+
Verify NTP client to multiple NTP servers and verify that one get selected
6+
"""
7+
8+
import infamy
9+
import infamy.ntp_server as ntp_server
10+
import infamy.ntp as ntp
11+
import infamy.util as util
12+
def config_target(dut, data1, data2, data3):
13+
dut.put_config_dicts({
14+
"ietf-interfaces": {
15+
"interfaces": {
16+
"interface": [
17+
{
18+
"name": data1,
19+
"enabled": True,
20+
"ipv4": {
21+
"address": [{
22+
"ip": "192.168.1.2",
23+
"prefix-length": 24
24+
}]
25+
}
26+
},
27+
{
28+
"name": data2,
29+
"enabled": True,
30+
"ipv4": {
31+
"address": [{
32+
"ip": "192.168.2.2",
33+
"prefix-length": 24
34+
}]
35+
}
36+
},
37+
{
38+
"name": data3,
39+
"enabled": True,
40+
"ipv4": {
41+
"address": [{
42+
43+
"ip": "192.168.3.2",
44+
"prefix-length": 24
45+
}]
46+
}
47+
}]
48+
}
49+
},
50+
"ietf-system": {
51+
"system": {
52+
"ntp": {
53+
"enabled": True,
54+
"server": [{
55+
"name": "Server1",
56+
"udp": {
57+
"address": "192.168.1.1"
58+
},
59+
"iburst": True
60+
},{
61+
"name": "Server2",
62+
"udp": {
63+
"address": "192.168.2.1"
64+
},
65+
"iburst": True
66+
},{
67+
"name": "Server3",
68+
"udp": {
69+
"address": "192.168.3.1"
70+
},
71+
"iburst": True
72+
}]
73+
}
74+
}
75+
}
76+
})
77+
78+
with infamy.Test() as test:
79+
with test.step("Set up topology and attach to target DUT"):
80+
env = infamy.Env()
81+
target = env.attach("target", "mgmt")
82+
83+
with test.step("Configure NTP client on 'target'"):
84+
_, data1 = env.ltop.xlate("target", "data1")
85+
_, data2 = env.ltop.xlate("target", "data2")
86+
_, data3 = env.ltop.xlate("target", "data3")
87+
88+
config_target(target, data1, data2, data3)
89+
90+
_, hport1 = env.ltop.xlate("host", "data1")
91+
_, hport2 = env.ltop.xlate("host", "data2")
92+
_, hport3 = env.ltop.xlate("host", "data3")
93+
94+
with infamy.IsolatedMacVlan(hport1) as ns1, \
95+
infamy.IsolatedMacVlan(hport2) as ns2, \
96+
infamy.IsolatedMacVlan(hport3) as ns3:
97+
ns1.addip("192.168.1.1")
98+
ns2.addip("192.168.2.1")
99+
ns3.addip("192.168.3.1")
100+
101+
with ntp_server.Server(ns1) as ntp1, \
102+
ntp_server.Server(ns2) as ntp2, \
103+
ntp_server.Server(ns3) as ntp3:
104+
with test.step("Verify one source is in 'selected' state on 'target'"):
105+
util.until(lambda: ntp.any_source_selected(target), attempts=200)
106+
107+
test.succeed()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../infamy/topologies/1x4.dot
Lines changed: 60 additions & 0 deletions
Loading

test/infamy/netconf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ def put_config_dicts(self, models):
318318
infer_put_dict(self.name, models)
319319

320320
for model in models.keys():
321+
print(model)
321322
mod = self.ly.get_module(model)
322323
lyd = mod.parse_data_dict(models[model], no_state=True, validate=False)
323324
config+=lyd.print_mem("xml", with_siblings=True, pretty=False)+"\n"

test/infamy/ntp.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
NTP client helper
3+
"""
4+
def _get_ntp(target):
5+
xpath="/ietf-system:system-state/infix-system:ntp"
6+
data=target.get_data(xpath)
7+
8+
if data is None:
9+
return None
10+
11+
return data["system-state"].get("infix-system:ntp", None) or data["system-state"].get("ntp", None)
12+
13+
def _get_ntp_sources(target):
14+
ntp=_get_ntp(target)
15+
16+
if ntp is None:
17+
return []
18+
19+
return ntp["sources"]["source"]
20+
21+
def any_source_selected(target):
22+
sources=_get_ntp_sources(target)
23+
24+
for source in sources:
25+
if source["source-state"] == "selected":
26+
return True
27+
28+
return False

test/infamy/ntp_server.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Start NTP server in the background"""
2+
import subprocess
3+
4+
class Server:
5+
def __init__(self, netns, iface="iface"):
6+
self.iface = iface
7+
self.process = None
8+
self.netns = netns
9+
10+
def __enter__(self):
11+
self.start()
12+
13+
def __exit__(self, _, __, ___):
14+
self.stop()
15+
16+
def start(self):
17+
cmd=f"ntpd -w -n -l -I {self.iface}"
18+
self.process = self.netns.popen(cmd.split(" "),stderr=subprocess.DEVNULL)
19+
20+
def stop(self):
21+
if self.process:
22+
self.process.terminate()
23+
self.process.wait()
24+
self.process = None

test/infamy/topologies/1x4.dot

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ graph "1x4" {
77
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
88

99
host [
10-
label="host | { <tgt> tgt | <data0> data0 | <data1> data1 | <data2> data2 }",
10+
label="host | { <mgmt> mgmt | <data1> data1 | <data2> data2 | <data3> data3 }",
1111
pos="0,12!",
1212
kind="controller",
1313
];
1414

1515
target [
16-
label="{ <mgmt> mgmt | <data0> data0 | <data1> data1 | <data2> data2 } | target",
16+
label="{ <mgmt> mgmt | <data1> data1 | <data2> data2 | <data3> data3 } | target",
1717
pos="10,12!",
1818

1919
kind="infix",
2020
];
2121

22-
host:tgt -- target:mgmt [kind=mgmt]
23-
host:data0 -- target:data0 [color=black]
22+
host:mgmt -- target:mgmt [kind=mgmt]
2423
host:data1 -- target:data1 [color=black]
2524
host:data2 -- target:data2 [color=black]
25+
host:data3 -- target:data3 [color=black]
2626
}

0 commit comments

Comments
 (0)