Skip to content

Commit eab4a9e

Browse files
[hostcfgd][dns] Subscribe to DNS_NAMESERVER table to react to static DNS configuration changes. (#49)
Changes are implemented according to sonic-net/SONiC#1262 HLD. Implement unit tests for each method of DnsCfg class.
1 parent 508d642 commit eab4a9e

3 files changed

Lines changed: 61 additions & 3 deletions

File tree

scripts/hostcfgd

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,16 @@ class RSyslogCfg(object):
16601660
self.cache['config'] = rsyslog_config
16611661
self.cache['servers'] = rsyslog_servers
16621662

1663+
1664+
class DnsCfg:
1665+
1666+
def load(self, *args, **kwargs):
1667+
self.dns_update()
1668+
1669+
def dns_update(self, *args, **kwargs):
1670+
run_cmd(['systemctl', 'restart', 'resolv-config'], True, False)
1671+
1672+
16631673
class HostConfigDaemon:
16641674
def __init__(self):
16651675
self.state_db_conn = DBConnector(STATE_DB, 0)
@@ -1713,6 +1723,9 @@ class HostConfigDaemon:
17131723
# Initialize RSyslogCfg
17141724
self.rsyslogcfg = RSyslogCfg()
17151725

1726+
# Initialize DnsCfg
1727+
self.dnscfg = DnsCfg()
1728+
17161729
def load(self, init_data):
17171730
features = init_data['FEATURE']
17181731
aaa = init_data['AAA']
@@ -1730,7 +1743,7 @@ class HostConfigDaemon:
17301743
mgmt_vrf = init_data.get(swsscommon.CFG_MGMT_VRF_CONFIG_TABLE_NAME, {})
17311744
syslog_cfg = init_data.get(swsscommon.CFG_SYSLOG_CONFIG_TABLE_NAME, {})
17321745
syslog_srv = init_data.get(swsscommon.CFG_SYSLOG_SERVER_TABLE_NAME, {})
1733-
1746+
dns = init_data.get('DNS_NAMESERVER', {})
17341747

17351748
self.feature_handler.sync_state_field(features)
17361749
self.aaacfg.load(aaa, tacacs_global, tacacs_server, radius_global, radius_server)
@@ -1740,7 +1753,9 @@ class HostConfigDaemon:
17401753
self.passwcfg.load(passwh)
17411754
self.devmetacfg.load(dev_meta)
17421755
self.mgmtifacecfg.load(mgmt_ifc, mgmt_vrf)
1756+
17431757
self.rsyslogcfg.load(syslog_cfg, syslog_srv)
1758+
self.dnscfg.load(dns)
17441759

17451760
# Update AAA with the hostname
17461761
self.aaacfg.hostname_update(self.devmetacfg.hostname)
@@ -1856,6 +1871,10 @@ class HostConfigDaemon:
18561871
syslog.syslog(syslog.LOG_INFO, 'SYSLOG_CONFIG table handler...')
18571872
self.rsyslog_handler()
18581873

1874+
def dns_nameserver_handler(self, key, op, data):
1875+
syslog.syslog(syslog.LOG_INFO, 'DNS nameserver handler...')
1876+
self.dnscfg.dns_update(key, data)
1877+
18591878
def wait_till_system_init_done(self):
18601879
# No need to print the output in the log file so using the "--quiet"
18611880
# flag
@@ -1909,6 +1928,8 @@ class HostConfigDaemon:
19091928
self.config_db.subscribe(swsscommon.CFG_SYSLOG_SERVER_TABLE_NAME,
19101929
make_callback(self.rsyslog_server_handler))
19111930

1931+
self.config_db.subscribe('DNS_NAMESERVER', make_callback(self.dns_nameserver_handler))
1932+
19121933
syslog.syslog(syslog.LOG_INFO,
19131934
"Waiting for systemctl to finish initialization")
19141935
self.wait_till_system_init_done()

tests/hostcfgd/hostcfgd_test.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ def test_devicemeta_event(self):
578578
daemon.aaacfg = mock.MagicMock()
579579
daemon.iptables = mock.MagicMock()
580580
daemon.passwcfg = mock.MagicMock()
581+
daemon.dnscfg = mock.MagicMock()
581582
daemon.load(HOSTCFG_DAEMON_INIT_CFG_DB)
582583
daemon.register_callbacks()
583584
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
@@ -644,6 +645,7 @@ def test_mgmtiface_event(self):
644645
daemon.aaacfg = mock.MagicMock()
645646
daemon.iptables = mock.MagicMock()
646647
daemon.passwcfg = mock.MagicMock()
648+
daemon.dnscfg = mock.MagicMock()
647649
daemon.load(HOSTCFG_DAEMON_INIT_CFG_DB)
648650
with mock.patch('hostcfgd.check_output_pipe') as mocked_check_output:
649651
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
@@ -670,3 +672,34 @@ def test_mgmtiface_event(self):
670672
call(['cat', '/proc/net/route'], ['grep', '-E', r"eth0\s+00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+202"], ['wc', '-l'])
671673
]
672674
mocked_check_output.assert_has_calls(expected)
675+
676+
def test_dns_events(self):
677+
MockConfigDb.set_config_db(HOSTCFG_DAEMON_CFG_DB)
678+
MockConfigDb.event_queue = [('DNS_NAMESERVER', '1.1.1.1')]
679+
daemon = hostcfgd.HostConfigDaemon()
680+
daemon.register_callbacks()
681+
with mock.patch('hostcfgd.run_cmd') as mocked_run_cmd:
682+
try:
683+
daemon.start()
684+
except TimeoutError:
685+
pass
686+
mocked_run_cmd.assert_has_calls([call(['systemctl', 'restart', 'resolv-config'], True, False)])
687+
688+
689+
class TestDnsHandler:
690+
691+
@mock.patch('hostcfgd.run_cmd')
692+
def test_dns_update(self, mock_run_cmd):
693+
dns_cfg = hostcfgd.DnsCfg()
694+
key = "1.1.1.1"
695+
dns_cfg.dns_update(key, {})
696+
697+
mock_run_cmd.assert_has_calls([call(['systemctl', 'restart', 'resolv-config'], True, False)])
698+
699+
def test_load(self):
700+
dns_cfg = hostcfgd.DnsCfg()
701+
dns_cfg.dns_update = mock.MagicMock()
702+
703+
data = {}
704+
dns_cfg.load(data)
705+
dns_cfg.dns_update.assert_called()

tests/hostcfgd/test_vectors.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,8 @@
11851185
"MGMT_INTERFACE": {},
11861186
"MGMT_VRF_CONFIG": {},
11871187
"SYSLOG_CONFIG": {},
1188-
"SYSLOG_SERVER": {}
1188+
"SYSLOG_SERVER": {},
1189+
"DNS_NAMESERVER": {}
11891190
}
11901191

11911192

@@ -1261,5 +1262,8 @@
12611262
"vrf_global": {
12621263
'mgmtVrfEnabled': 'true'
12631264
}
1264-
}
1265+
},
1266+
"DNS_NAMESERVER": {
1267+
"1.1.1.1": {}
1268+
},
12651269
}

0 commit comments

Comments
 (0)