Skip to content

Commit 11da264

Browse files
abdosidaall
andauthored
Fix the issue when persistent DVS is used to run pytest which has number of front-panel ports < 32 (#1373)
* Fix the issue where persistent DVS is used to run pytest and ports are created dynamically (ref pr: sonic-net/sonic-buildimage#4499). There were two issues: a) since number of dynamic front port can be < 32 test case fails as it expect always 32. Make sure to udpate persitent DVS to always have 32 ports/server link as part of test run and save the current config db b) after test is done persistent DVS need to be moved to original state. Make dure to remove extra port/server link and restore back config db Signed-off-by: Abhishek Dosi <[email protected]> * Review Comments fix Signed-off-by: Abhishek Dosi <[email protected]> * Added option for force persitent dvs if port < 32 Updated Readme Signed-off-by: Abhishek Dosi <[email protected]> * Fix LGTM Signed-off-by: Abhishek Dosi <[email protected]> * Fix LGTM and compile error Signed-off-by: Abhishek Dosi <[email protected]> * Update tests/conftest.py Co-authored-by: Danny Allen <[email protected]> Co-authored-by: Danny Allen <[email protected]>
1 parent d904f3e commit 11da264

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

tests/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ For those developing new features for SWSS or the DVS framework, you might find
7171
```
7272
sudo pytest --dvsname=vs
7373
```
74+
By default if number of ports in persistent DVS < 32 (needed by testbed) then test will be aborted. To overcome that --forcedvs option can be used.
75+
76+
```
77+
sudo pytest --dvsname=vs --forcedvs
78+
```
79+
7480
7581
5. Additionally, if you need to simulate a specific hardware platform (e.g. Broadcom or Mellanox), you can add this environment variable when starting the DVS container:
7682

tests/conftest.py

+48-4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ def ensure_system(cmd):
4141
def pytest_addoption(parser):
4242
parser.addoption("--dvsname", action="store", default=None,
4343
help="dvs name")
44+
parser.addoption("--forcedvs", action="store_true", default=False,
45+
help="force persistent dvs when ports < 32")
4446
parser.addoption("--keeptb", action="store_true", default=False,
4547
help="keep testbed after test")
4648
parser.addoption("--imgname", action="store", default="docker-sonic-vs",
@@ -191,7 +193,8 @@ def __init__(
191193
keeptb=False,
192194
fakeplatform=None,
193195
log_path=None,
194-
max_cpu=2
196+
max_cpu=2,
197+
forcedvs=None,
195198
):
196199
self.basicd = ['redis-server',
197200
'rsyslogd']
@@ -220,6 +223,7 @@ def __init__(
220223
self.cleanup = False
221224
else:
222225
self.cleanup = True
226+
self.persistent = False
223227
if name != None:
224228
# get virtual switch container
225229
for ctn in self.client.containers.list():
@@ -230,10 +234,20 @@ def __init__(
230234
else:
231235
(status, output) = subprocess.getstatusoutput("docker inspect --format '{{.HostConfig.NetworkMode}}' %s" % name)
232236
ctn_sw_id = output.split(':')[1]
237+
# Persistent DVS is available.
233238
self.cleanup = False
239+
self.persistent = True
234240
if self.ctn == None:
235241
raise NameError("cannot find container %s" % name)
236242

243+
self.num_net_interfaces = self.net_interface_count()
244+
245+
if self.num_net_interfaces > NUM_PORTS:
246+
raise ValueError("persistent dvs is not valid for testbed with ports > %d" % NUM_PORTS)
247+
248+
if self.num_net_interfaces < NUM_PORTS and not forcedvs:
249+
raise ValueError("persistent dvs does not have %d ports needed by testbed" % NUM_PORTS)
250+
237251
# get base container
238252
for ctn in self.client.containers.list():
239253
if ctn.id == ctn_sw_id or ctn.name == ctn_sw_id:
@@ -254,6 +268,10 @@ def __init__(
254268
self.mount = "/var/run/redis-vs/{}".format(ctn_sw_name)
255269

256270
self.net_cleanup()
271+
# As part of https://github.com/Azure/sonic-buildimage/pull/4499
272+
# VS support dynamically create Front-panel ports so save the orginal
273+
# config db for persistent DVS
274+
self.runcmd("mv /etc/sonic/config_db.json /etc/sonic/config_db.json.orig")
257275
self.ctn_restart()
258276
else:
259277
self.ctn_sw = self.client.containers.run('debian:jessie', privileged=True, detach=True,
@@ -301,7 +319,13 @@ def __init__(
301319
def destroy(self):
302320
if self.appldb:
303321
del self.appldb
304-
if self.cleanup:
322+
# In case persistent dvs was used removed all the extra server link
323+
# that were created
324+
if self.persistent:
325+
for s in self.servers:
326+
s.destroy()
327+
# persistent and clean-up flag are mutually exclusive
328+
elif self.cleanup:
305329
self.ctn.remove(force=True)
306330
self.ctn_sw.remove(force=True)
307331
os.system("rm -rf {}".format(self.mount))
@@ -418,6 +442,21 @@ def net_cleanup(self):
418442
print("remove extra link {}".format(pname))
419443
return
420444

445+
def net_interface_count(self):
446+
"""get the interface count in persistent DVS Container
447+
if not found or some error then return 0 as default"""
448+
449+
res = self.ctn.exec_run(['sh', '-c', 'ip link show | grep -oE eth[0-9]+ | grep -vc eth0'])
450+
if not res.exit_code:
451+
try:
452+
out = res.output.decode('utf-8')
453+
except AttributeError:
454+
return 0
455+
return int(out.rstrip('\n'))
456+
else:
457+
return 0
458+
459+
421460
def ctn_restart(self):
422461
self.ctn.restart()
423462

@@ -906,7 +945,7 @@ def remove_neighbor(self, interface, ip):
906945
def add_route(self, prefix, nexthop):
907946
self.runcmd("ip route add " + prefix + " via " + nexthop)
908947
time.sleep(1)
909-
948+
910949
def remove_route(self, prefix):
911950
self.runcmd("ip route del " + prefix)
912951
time.sleep(1)
@@ -1008,18 +1047,23 @@ def get_state_db(self):
10081047
@pytest.yield_fixture(scope="module")
10091048
def dvs(request) -> DockerVirtualSwitch:
10101049
name = request.config.getoption("--dvsname")
1050+
forcedvs = request.config.getoption("--forcedvs")
10111051
keeptb = request.config.getoption("--keeptb")
10121052
imgname = request.config.getoption("--imgname")
10131053
max_cpu = request.config.getoption("--max_cpu")
10141054
fakeplatform = getattr(request.module, "DVS_FAKE_PLATFORM", None)
10151055
log_path = name if name else request.module.__name__
10161056

1017-
dvs = DockerVirtualSwitch(name, imgname, keeptb, fakeplatform, log_path, max_cpu)
1057+
dvs = DockerVirtualSwitch(name, imgname, keeptb, fakeplatform, log_path, max_cpu, forcedvs)
10181058

10191059
yield dvs
10201060

10211061
dvs.get_logs()
10221062
dvs.destroy()
1063+
# restore original config db
1064+
if dvs.persistent:
1065+
dvs.runcmd("mv /etc/sonic/config_db.json.orig /etc/sonic/config_db.json")
1066+
dvs.ctn_restart()
10231067

10241068
@pytest.yield_fixture
10251069
def testlog(request, dvs):

0 commit comments

Comments
 (0)