Skip to content

Commit 08f1fbe

Browse files
Update management interface related configuration in MGMT_PORT_TABLE in STATE_DB (#21813)
Currently Management interface related data is present in CONFIG_DB and 'oper_status' is present in STATE_DB MGMT_PORT_TABLE. This PR change is made to ensure that all telemetry data related to management interface is present in STATE_DB. Signed-off-by: Suvarna Meenakshi <sumeenak@microsoft.com>
1 parent 47d2ad9 commit 08f1fbe

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

files/image_config/monit/mgmt_oper_status.py

+21-8
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,46 @@
66
import subprocess
77
import syslog
88

9-
from sonic_py_common import multi_asic, device_info
109
from swsscommon.swsscommon import SonicV2Connector
1110

1211

1312
def main():
1413
db = SonicV2Connector(use_unix_socket_path=True)
1514
db.connect('CONFIG_DB')
1615
db.connect('STATE_DB')
17-
mgmt_ports_keys = db.keys(db.CONFIG_DB, 'MGMT_PORT|*' )
16+
mgmt_ports_keys = db.keys(db.CONFIG_DB, 'MGMT_PORT|*')
1817
if not mgmt_ports_keys:
1918
syslog.syslog(syslog.LOG_DEBUG, 'No management interface found')
2019
else:
2120
try:
22-
mgmt_ports = [key.split('MGMT_PORT|')[-1] for key in mgmt_ports_keys]
21+
mgmt_ports = [key.split('MGMT_PORT|')[-1] for key
22+
in mgmt_ports_keys]
2323
for port in mgmt_ports:
24-
state_db_mgmt_port = db.keys(db.STATE_DB, 'MGMT_PORT_TABLE|*' )
24+
state_db_mgmt_keys = db.keys(db.STATE_DB, 'MGMT_PORT_TABLE|*')
2525
state_db_key = "MGMT_PORT_TABLE|{}".format(port)
26-
prev_oper_status = 'unknown'
27-
if state_db_key in state_db_mgmt_port:
28-
prev_oper_status = db.get(db.STATE_DB, state_db_key, 'oper_status')
26+
config_db_key = "MGMT_PORT|{}".format(port)
27+
config_db_mgmt = db.get_all(db.CONFIG_DB, config_db_key)
28+
state_db_mgmt = db.get_all(db.STATE_DB, state_db_key) if state_db_key in state_db_mgmt_keys else {}
29+
30+
# Sync fields from CONFIG_DB MGMT_PORT table to STATE_DB MGMT_PORT_TABLE
31+
for field in config_db_mgmt:
32+
if field != 'oper_status':
33+
# Update STATE_DB if port is not present or value differs from
34+
# CONFIG_DB
35+
if (field in state_db_mgmt and state_db_mgmt[field] != config_db_mgmt[field]) \
36+
or field not in state_db_mgmt:
37+
db.set(db.STATE_DB, state_db_key, field, config_db_mgmt[field])
38+
39+
# Update oper status if modified
40+
prev_oper_status = state_db_mgmt.get('oper_status', 'unknown')
2941
port_operstate_path = '/sys/class/net/{}/operstate'.format(port)
3042
oper_status = subprocess.run(['cat', port_operstate_path], capture_output=True, text=True)
3143
current_oper_status = oper_status.stdout.strip()
3244
if current_oper_status != prev_oper_status:
3345
db.set(db.STATE_DB, state_db_key, 'oper_status', current_oper_status)
34-
log_level = syslog.LOG_INFO if current_oper_status == 'up' else syslog.LOG_WARNING
46+
log_level = syslog.LOG_INFO if current_oper_status == 'up' else syslog.LOG_WARNING
3547
syslog.syslog(log_level, "mgmt_oper_status: {}".format(current_oper_status))
48+
3649
except Exception as e:
3750
syslog.syslog(syslog.LOG_ERR, "mgmt_oper_status exception : {}".format(str(e)))
3851
db.set(db.STATE_DB, state_db_key, 'oper_status', 'unknown')

files/image_config/monit/tests/test_mgmt_oper_status.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ def test_main_with_mgmt_ports(self, mock_syslog, mock_subprocess, mock_SonicV2Co
2929
mock_db.keys.return_value = mgmt_ports_keys
3030
mock_db.set.return_value = None
3131

32+
def get_all_side_effect(db_name, key):
33+
if db_name == mock_db.CONFIG_DB:
34+
return {'admin_status': 'up', 'alias': 'mgmt', 'speed': '1000'}
35+
elif db_name == mock_db.STATE_DB:
36+
return {'admin_status': 'up', 'alias': 'Management'}
37+
return {}
38+
mock_db.get_all.side_effect = get_all_side_effect
39+
40+
def keys_side_effect(db_name, key_regex):
41+
if db_name == mock_db.CONFIG_DB:
42+
return ['MGMT_PORT|eth0', 'MGMT_PORT|eth1']
43+
elif db_name == mock_db.STATE_DB:
44+
return ['MGMT_PORT_TABLE|eth0', 'MGMT_PORT_TABLE|eth1']
45+
return {}
46+
mock_db.keys.side_effect = keys_side_effect
47+
3248
mock_subprocess.return_value = subprocess.CompletedProcess(args=['cat', '/sys/class/net/eth0/operstate'], returncode=0, stdout='up', stderr='')
3349

3450
mgmt_oper_status.main()
@@ -38,6 +54,12 @@ def test_main_with_mgmt_ports(self, mock_syslog, mock_subprocess, mock_SonicV2Co
3854

3955
mock_db.set.assert_any_call(mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth0', 'oper_status', 'up')
4056
mock_db.set.assert_any_call(mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth1', 'oper_status', 'up')
57+
# Assert STATE_DB was updated with field that was not present in CONFIG_DB
58+
mock_db.set.assert_any_call(mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth1', 'speed', '1000')
59+
# Assert STATE_DB was updated with alias with updated value from CONFIG_DB
60+
mock_db.set.assert_any_call(mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth1', 'alias', 'mgmt')
61+
# Assert STATE_DB was NOT updated with field is already present and value is not modified
62+
assert not any(call[0] == (mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth1', 'admin_status', 'up') for call in mock_db.set.call_args_list)
4163

4264
@patch('mgmt_oper_status.SonicV2Connector')
4365
@patch('mgmt_oper_status.subprocess.run')
@@ -69,8 +91,8 @@ def test_main_exception_handling(self, mock_syslog, mock_subprocess, mock_SonicV
6991
mock_db.set.return_value = None
7092

7193
mock_subprocess.side_effect = Exception("File not found")
72-
73-
mgmt_oper_status.main()
94+
with self.assertRaises(SystemExit) as cm:
95+
mgmt_oper_status.main()
7496

7597
mock_syslog.assert_called_with(syslog.LOG_ERR, "mgmt_oper_status exception : File not found")
7698
mock_db.set.assert_any_call(mock_db.STATE_DB, 'MGMT_PORT_TABLE|eth0', 'oper_status', 'unknown')

0 commit comments

Comments
 (0)