Skip to content

Commit 8a65ac9

Browse files
committed
Fix multi asic connection
Signed-off-by: gpunathilell <gpunathilell@nvidia.com>
1 parent 3e3daf3 commit 8a65ac9

2 files changed

Lines changed: 79 additions & 3 deletions

File tree

tests/portstat_test.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,3 +1119,74 @@ def teardown_class(cls):
11191119
os.environ["UTILITIES_UNIT_TESTING"] = "0"
11201120
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
11211121
remove_tmp_cnstat_file()
1122+
1123+
1124+
class TestPortstatGetDbClient(object):
1125+
"""Test the get_db_client method for caching DB connections"""
1126+
1127+
def test_get_db_client_creates_new_connection(self):
1128+
"""Test that get_db_client creates a new connection when none exists"""
1129+
from unittest import mock
1130+
from utilities_common.portstat import Portstat
1131+
from utilities_common.constants import DEFAULT_NAMESPACE
1132+
1133+
portstat = Portstat(namespace=DEFAULT_NAMESPACE, display_option='')
1134+
1135+
with mock.patch('sonic_py_common.multi_asic.connect_to_all_dbs_for_ns') as mock_connect:
1136+
mock_db_client = mock.MagicMock()
1137+
mock_connect.return_value = mock_db_client
1138+
1139+
result = portstat.get_db_client('asic0')
1140+
1141+
mock_connect.assert_called_once_with('asic0')
1142+
1143+
assert result == mock_db_client
1144+
1145+
assert portstat.db_clients['asic0'] == mock_db_client
1146+
1147+
def test_get_db_client_returns_cached_connection(self):
1148+
"""Test that get_db_client returns cached connection on subsequent calls"""
1149+
from unittest import mock
1150+
from utilities_common.portstat import Portstat
1151+
from utilities_common.constants import DEFAULT_NAMESPACE
1152+
1153+
portstat = Portstat(namespace=DEFAULT_NAMESPACE, display_option='')
1154+
1155+
with mock.patch('sonic_py_common.multi_asic.connect_to_all_dbs_for_ns') as mock_connect:
1156+
mock_db_client = mock.MagicMock()
1157+
mock_connect.return_value = mock_db_client
1158+
result1 = portstat.get_db_client('asic0')
1159+
result2 = portstat.get_db_client('asic0')
1160+
mock_connect.assert_called_once_with('asic0')
1161+
1162+
assert result1 == result2
1163+
assert result1 == mock_db_client
1164+
1165+
def test_get_db_client_multiple_namespaces(self):
1166+
"""Test that get_db_client handles multiple namespaces correctly"""
1167+
from unittest import mock
1168+
from utilities_common.portstat import Portstat
1169+
from utilities_common.constants import DEFAULT_NAMESPACE
1170+
1171+
portstat = Portstat(namespace=DEFAULT_NAMESPACE, display_option='')
1172+
1173+
with mock.patch('sonic_py_common.multi_asic.connect_to_all_dbs_for_ns') as mock_connect:
1174+
mock_db_client_asic0 = mock.MagicMock()
1175+
mock_db_client_asic1 = mock.MagicMock()
1176+
1177+
def side_effect(ns):
1178+
if ns == 'asic0':
1179+
return mock_db_client_asic0
1180+
elif ns == 'asic1':
1181+
return mock_db_client_asic1
1182+
1183+
mock_connect.side_effect = side_effect
1184+
result_asic0 = portstat.get_db_client('asic0')
1185+
result_asic1 = portstat.get_db_client('asic1')
1186+
assert mock_connect.call_count == 2
1187+
mock_connect.assert_any_call('asic0')
1188+
mock_connect.assert_any_call('asic1')
1189+
assert result_asic0 == mock_db_client_asic0
1190+
assert result_asic1 == mock_db_client_asic1
1191+
assert portstat.db_clients['asic0'] == mock_db_client_asic0
1192+
assert portstat.db_clients['asic1'] == mock_db_client_asic1

utilities_common/portstat.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def __init__(self, namespace, display_option):
166166
if device_info.is_supervisor():
167167
self.db = SonicV2Connector(use_unix_socket_path=False)
168168
self.db.connect(self.db.CHASSIS_STATE_DB, False)
169-
169+
self.db_clients = {}
170170
self.sorted = natsorted
171171

172172
def get_cnstat_dict(self):
@@ -370,7 +370,7 @@ def get_port_speed(self, port_name):
370370
state_db_table_id = PORT_STATE_TABLE_PREFIX + port_name
371371
app_db_table_id = PORT_STATUS_TABLE_PREFIX + port_name
372372
for ns in self.multi_asic.get_ns_list_based_on_options():
373-
self.db = multi_asic.connect_to_all_dbs_for_ns(ns)
373+
self.db = self.get_db_client(ns)
374374
speed = self.db.get(self.db.STATE_DB, state_db_table_id, PORT_SPEED_FIELD)
375375
oper_status = self.db.get(self.db.APPL_DB, app_db_table_id, PORT_OPER_STATUS_FIELD)
376376
if speed is None or speed == STATUS_NA or oper_status != "up":
@@ -379,6 +379,11 @@ def get_port_speed(self, port_name):
379379
return int(speed)
380380
return STATUS_NA
381381

382+
def get_db_client(self, ns):
383+
if not self.db_clients.get(ns):
384+
self.db_clients[ns] = multi_asic.connect_to_all_dbs_for_ns(ns)
385+
return self.db_clients[ns]
386+
382387
def get_port_state(self, port_name):
383388
"""
384389
Get the port state
@@ -392,7 +397,7 @@ def get_port_state(self, port_name):
392397

393398
full_table_id = PORT_STATUS_TABLE_PREFIX + port_name
394399
for ns in self.multi_asic.get_ns_list_based_on_options():
395-
self.db = multi_asic.connect_to_all_dbs_for_ns(ns)
400+
self.db = self.get_db_client(ns)
396401
admin_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_ADMIN_STATUS_FIELD)
397402
oper_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_OPER_STATUS_FIELD)
398403

0 commit comments

Comments
 (0)