Skip to content

Commit 47fd128

Browse files
[Banner] Added BannerCfg class to hostcfgd to handle Banner messages (#79)
- Why I did it Added Banner feature related hostcfgd service according to HLD: sonic-net/SONiC#1361 This PR depends on the following PR: sonic-net/sonic-swss-common#826 - How I did it Added BannerCfg service to hostcfgd. It handles Config DB changes and restart "banner-config" systemd service which will update banners. - How to verify it Manual test Signed-off-by: Yevhen Fastiuk <[email protected]> Co-authored-by: Yevhen Fastiuk <[email protected]>
1 parent b7f26d4 commit 47fd128

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

scripts/hostcfgd

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,6 +1749,84 @@ class SerialConsoleCfg:
17491749
return
17501750

17511751

1752+
class BannerCfg(object):
1753+
"""
1754+
Banner Config Daemon
1755+
Handles changes in BANNER_MESSAGE table.
1756+
1) Handle change of feature state
1757+
2) Handle change of login message
1758+
3) Handle change of MOTD message
1759+
4) Handle change of logout message
1760+
"""
1761+
1762+
def __init__(self):
1763+
self.cache = {}
1764+
1765+
def load(self, banner_messages_config: dict):
1766+
"""Banner messages configuration
1767+
1768+
Force load banner configuration. Login messages should be taken at boot-time by
1769+
SSH daemon.
1770+
1771+
Args:
1772+
banners_message_config: Configured banner messages.
1773+
"""
1774+
1775+
syslog.syslog(syslog.LOG_INFO, 'BannerCfg: load initial')
1776+
1777+
if not banner_messages_config:
1778+
banner_messages_config = {}
1779+
1780+
# Force load banner messages.
1781+
# Login messages show be taken at boot-time by SSH daemon.
1782+
state_data = banner_messages_config.get("state", {})
1783+
login_data = banner_messages_config.get("login", {})
1784+
motd_data = banner_messages_config.get("motd", {})
1785+
logout_data = banner_messages_config.get("logout", {})
1786+
1787+
self.banner_message("state", state_data)
1788+
self.banner_message("login", login_data)
1789+
self.banner_message("motd", motd_data)
1790+
self.banner_message("logout", logout_data)
1791+
1792+
def banner_message(self, key, data):
1793+
"""
1794+
Apply banner message handler.
1795+
1796+
Args:
1797+
cache: Cache to compare/save data.
1798+
db: DB instance.
1799+
table: DB table that was changed.
1800+
key: DB table's key that was triggered change.
1801+
data: Read table data.
1802+
"""
1803+
# Handling state, login/logout and MOTD messages. Data should be a dict
1804+
if type(data) != dict:
1805+
# Nothing to handle
1806+
return
1807+
1808+
update_required = False
1809+
# Check with cache
1810+
for k,v in data.items():
1811+
if v != self.cache.get(k):
1812+
update_required = True
1813+
break
1814+
1815+
if update_required == False:
1816+
return
1817+
1818+
try:
1819+
run_cmd(["systemctl", "restart", "banner-config"], True, True)
1820+
except Exception:
1821+
syslog.syslog(syslog.LOG_ERR, 'BannerCfg: Failed to restart '
1822+
'banner-config service')
1823+
return
1824+
1825+
# Update cache
1826+
for k,v in data.items():
1827+
self.cache[k] = v
1828+
1829+
17521830
class HostConfigDaemon:
17531831
def __init__(self):
17541832
self.state_db_conn = DBConnector(STATE_DB, 0)
@@ -1803,6 +1881,9 @@ class HostConfigDaemon:
18031881
# Initialize SerialConsoleCfg
18041882
self.serialconscfg = SerialConsoleCfg()
18051883

1884+
# Initialize BannerCfg
1885+
self.bannermsgcfg = BannerCfg()
1886+
18061887
def load(self, init_data):
18071888
aaa = init_data['AAA']
18081889
tacacs_global = init_data['TACPLUS']
@@ -1826,6 +1907,7 @@ class HostConfigDaemon:
18261907
ntp_servers = init_data.get(swsscommon.CFG_NTP_SERVER_TABLE_NAME)
18271908
ntp_keys = init_data.get(swsscommon.CFG_NTP_KEY_TABLE_NAME)
18281909
serial_console = init_data.get('SERIAL_CONSOLE', {})
1910+
banner_messages = init_data.get(swsscommon.CFG_BANNER_MESSAGE_TABLE_NAME)
18291911

18301912
self.aaacfg.load(aaa, tacacs_global, tacacs_server, radius_global, radius_server, ldap_global, ldap_server)
18311913
self.iptables.load(lpbk_table)
@@ -1839,6 +1921,8 @@ class HostConfigDaemon:
18391921
self.fipscfg.load(fips_cfg)
18401922
self.ntpcfg.load(ntp_global, ntp_servers, ntp_keys)
18411923
self.serialconscfg.load(serial_console)
1924+
self.bannermsgcfg.load(banner_messages)
1925+
18421926
self.pamLimitsCfg.update_config_file()
18431927

18441928
# Update AAA with the hostname
@@ -1992,6 +2076,10 @@ class HostConfigDaemon:
19922076
syslog.syslog(syslog.LOG_INFO, 'SERIAL_CONSOLE table handler...')
19932077
self.serialconscfg.update_serial_console_cfg(key, data)
19942078

2079+
def banner_handler(self, key, op, data):
2080+
syslog.syslog(syslog.LOG_INFO, 'BANNER_MESSAGE table handler...')
2081+
self.bannermsgcfg.banner_message(key, data)
2082+
19952083
def wait_till_system_init_done(self):
19962084
# No need to print the output in the log file so using the "--quiet"
19972085
# flag
@@ -2059,6 +2147,10 @@ class HostConfigDaemon:
20592147
self.config_db.subscribe(swsscommon.CFG_NTP_KEY_TABLE_NAME,
20602148
make_callback(self.ntp_srv_key_handler))
20612149

2150+
# Handle BANNER_MESSAGE changes
2151+
self.config_db.subscribe(swsscommon.CFG_BANNER_MESSAGE_TABLE_NAME,
2152+
make_callback(self.banner_handler))
2153+
20622154
syslog.syslog(syslog.LOG_INFO,
20632155
"Waiting for systemctl to finish initialization")
20642156
self.wait_till_system_init_done()

tests/hostcfgd/hostcfgd_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,20 @@ def test_load(self):
354354
data = {}
355355
dns_cfg.load(data)
356356
dns_cfg.dns_update.assert_called()
357+
358+
359+
class TestBannerCfg:
360+
def test_load(self):
361+
banner_cfg = hostcfgd.BannerCfg()
362+
banner_cfg.banner_message = mock.MagicMock()
363+
364+
data = {}
365+
banner_cfg.load(data)
366+
banner_cfg.banner_message.assert_called()
367+
368+
@mock.patch('hostcfgd.run_cmd')
369+
def test_banner_message(self, mock_run_cmd):
370+
banner_cfg = hostcfgd.BannerCfg()
371+
banner_cfg.banner_message(None, {'test': 'test'})
372+
373+
mock_run_cmd.assert_has_calls([call(['systemctl', 'restart', 'banner-config'], True, True)])

0 commit comments

Comments
 (0)