Skip to content

Commit 3ef484c

Browse files
committed
errors
1 parent 4e25cfb commit 3ef484c

File tree

2 files changed

+90
-113
lines changed

2 files changed

+90
-113
lines changed

scripts/hostcfgd

Lines changed: 33 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,88 +1694,43 @@ class FipsCfg(object):
16941694
syslog.syslog(syslog.LOG_INFO, f'FipsCfg: update the FIPS enforce option {self.enforce}.')
16951695
loader.set_fips(image, self.enforce)
16961696

1697-
class Memory_StatisticsCfg(object):
1698-
"""
1699-
Memory Stats Config Daemon
1700-
Handles changes in MEMORY_STATS table.
1701-
1) Handle enabling or disabling the feature
1702-
2) Handle change of retention period
1703-
3) Handle change of sampling interval
1704-
"""
1705-
1706-
def __init__(self, config_db):
1707-
self.config_db = config_db
1708-
self.cache = {}
1709-
self.memory_statistics_defaults = {
1710-
"enabled": "false",
1711-
"retention_time": "15 days",
1712-
"sampling_interval": "5 minutes"
1713-
}
1714-
1715-
def load(self, memory_stats_config: dict):
1716-
"""
1717-
Load memory statistics configuration when the daemon starts.
1718-
Args:
1719-
memory_stats_config: Configured memory statistics settings.
1720-
"""
1721-
syslog.syslog(syslog.LOG_INFO, "Memory_StatisticsCfg init ...")
1722-
memory_statistics_conf = memory_stats_config.get("config", {})
1723-
1724-
# Apply default configurations if not present
1725-
for row, value in self.memory_statistics_defaults.items():
1726-
if not memory_statistics_conf.get(row):
1727-
self.config_db.mod_entry("MEMORY_STATISTICS", "config", {row: value})
1728-
1729-
# Apply configurations to ensure they are set correctly on startup
1730-
self.apply_configuration(memory_statistics_conf)
1697+
class Memory_StatisticsCfg:
1698+
def __init__(self):
1699+
self.enabled = False
1700+
self.retention_time = 0
1701+
self.sampling_interval = 0
17311702

1732-
def apply_configuration(self, config):
1733-
"""
1734-
Apply the memory statistics configuration settings.
1735-
Args:
1736-
config: Configuration data for memory statistics.
1737-
"""
1738-
# Determine if the feature is enabled or disabled
1739-
enabled = config.get("enabled", self.memory_statistics_defaults["enabled"]).lower() == "true"
1740-
retention_time = config.get("retention_time", self.memory_statistics_defaults["retention_time"])
1741-
sampling_interval = config.get("sampling_interval", self.memory_statistics_defaults["sampling_interval"])
1742-
1743-
# Enable or disable memory statistics
1744-
if enabled:
1745-
self.run_cmd(["sonic-memory_statistics-config", "--enable"])
1703+
def load_config(self, config_data):
1704+
try:
1705+
config = json.loads(config_data)
1706+
self.enabled = config.get("enabled", self.enabled)
1707+
self.retention_time = config.get("retention_time", self.retention_time)
1708+
self.sampling_interval = config.get("sampling_interval", self.sampling_interval)
1709+
except json.JSONDecodeError:
1710+
raise ValueError("Invalid JSON format for configuration data")
1711+
1712+
def apply_config(self):
1713+
if self.enabled:
1714+
self._run_shell_command(f"set_memory_statistics --enable --retention-time {self.retention_time} --sampling-interval {self.sampling_interval}")
17461715
else:
1747-
self.run_cmd(["sonic-memory_statistics-config", "--disable"])
1748-
1749-
# Set retention time and sampling interval
1750-
self.run_cmd(["sonic-memory_statistics-config", "--retention-time", retention_time])
1751-
self.run_cmd(["sonic-memory_statistics-config", "--sampling-interval", sampling_interval])
1716+
self._run_shell_command("set_memory_statistics --disable")
1717+
1718+
def update_config(self, key, value):
1719+
if key == "enabled":
1720+
self.enabled = value
1721+
elif key == "retention_time":
1722+
self.retention_time = value
1723+
elif key == "sampling_interval":
1724+
self.sampling_interval = value
1725+
else:
1726+
raise ValueError(f"Unknown configuration key: {key}")
17521727

1753-
def memory_statistics_update(self, key, data):
1754-
"""
1755-
Handle updates to the memory statistics configuration.
1756-
Args:
1757-
key: Key identifying the config type.
1758-
data: Updated configuration data.
1759-
"""
1760-
syslog.syslog(syslog.LOG_INFO, "Memory_Statistics global configuration update")
1761-
if key == "config":
1762-
self.apply_configuration(data)
1728+
self.apply_config()
17631729

1764-
def run_cmd(self, cmd):
1765-
"""
1766-
Execute a shell command and return the output.
1767-
Args:
1768-
cmd: List of command arguments.
1769-
"""
1770-
try:
1771-
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
1772-
syslog.syslog(syslog.LOG_INFO, output.decode('utf-8'))
1773-
except subprocess.CalledProcessError as e:
1774-
syslog.syslog(syslog.LOG_ERR, e.output.decode('utf-8'))
1775-
except FileNotFoundError:
1776-
syslog.syslog(syslog.LOG_ERR, f"Command not found: {' '.join(cmd)}")
1777-
except Exception as e:
1778-
syslog.syslog(syslog.LOG_ERR, f"An unexpected error occurred: {str(e)}")
1730+
def _run_shell_command(self, command):
1731+
result = subprocess.run(command, shell=True, text=True, capture_output=True)
1732+
if result.returncode != 0:
1733+
raise RuntimeError(f"Shell command failed with error: {result.stderr}")
17791734

17801735
class HostConfigDaemon:
17811736
def __init__(self):

tests/hostcfgd/hostcfgd_test.py

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -294,41 +294,63 @@ def test_dns_events(self):
294294
pass
295295
mocked_run_cmd.assert_has_calls([call(['systemctl', 'restart', 'resolv-config'], True, False)])
296296

297-
def test_memory_statistics_event(self):
298-
HOSTCFG_DAEMON_CFG_DB = {
299-
'MEMORY_STATISTICS': {
300-
'config': {
301-
'enabled': 'true',
302-
'retention_time': '15 days',
303-
'sampling_interval': '5 minutes'
304-
}
305-
}
306-
}
307-
308-
MockConfigDb.set_config_db(HOSTCFG_DAEMON_CFG_DB)
309-
daemon = hostcfgd.HostConfigDaemon()
310-
daemon.register_callbacks()
311-
MockConfigDb.event_queue = [('MEMORY_STATISTICS', 'config')]
312-
313-
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
314-
popen_mock = mock.Mock()
315-
attrs = {'communicate.return_value': ('output', 'error')}
316-
popen_mock.configure_mock(**attrs)
317-
mocked_subprocess.Popen.return_value = popen_mock
318-
mocked_subprocess.check_call = mock.Mock()
319-
320-
try:
321-
daemon.start()
322-
except TimeoutError:
323-
pass
324-
325-
expected_calls = [
326-
mock.call(['sonic-memory_statistics-config', '--enable']),
327-
mock.call(['sonic-memory_statistics-config', '--retention_time', '15 days']),
328-
mock.call(['sonic-memory_statistics-config', '--sampling_interval', '5 minutes'])
329-
]
330-
331-
mocked_subprocess.check_call.assert_has_calls(expected_calls, any_order=True)
297+
class TestMemoryStatisticsCfg(unittest.TestCase):
298+
def setUp(self):
299+
self.cfg = Memory_StatisticsCfg()
300+
301+
@patch('hostcfgd.subprocess.run')
302+
def test_load_config(self, mock_run):
303+
config_data = json.dumps({
304+
"enabled": True,
305+
"retention_time": 3600,
306+
"sampling_interval": 60
307+
})
308+
self.cfg.load_config(config_data)
309+
self.assertTrue(self.cfg.enabled)
310+
self.assertEqual(self.cfg.retention_time, 3600)
311+
self.assertEqual(self.cfg.sampling_interval, 60)
312+
313+
@patch('hostcfgd.subprocess.run')
314+
def test_apply_config_enable(self, mock_run):
315+
self.cfg.enabled = True
316+
self.cfg.retention_time = 3600
317+
self.cfg.sampling_interval = 60
318+
self.cfg.apply_config()
319+
mock_run.assert_called_once_with(
320+
'set_memory_statistics --enable --retention-time 3600 --sampling-interval 60',
321+
shell=True, text=True, capture_output=True
322+
)
323+
324+
@patch('hostcfgd.subprocess.run')
325+
def test_apply_config_disable(self, mock_run):
326+
self.cfg.enabled = False
327+
self.cfg.apply_config()
328+
mock_run.assert_called_once_with(
329+
'set_memory_statistics --disable',
330+
shell=True, text=True, capture_output=True
331+
)
332+
333+
@patch('hostcfgd.subprocess.run')
334+
def test_update_config(self, mock_run):
335+
self.cfg.update_config('retention_time', 7200)
336+
self.assertEqual(self.cfg.retention_time, 7200)
337+
mock_run.assert_called_once_with(
338+
'set_memory_statistics --enable --retention-time 7200 --sampling-interval 0',
339+
shell=True, text=True, capture_output=True
340+
)
341+
342+
@patch('hostcfgd.subprocess.run')
343+
def test_update_config_invalid_key(self, mock_run):
344+
with self.assertRaises(ValueError) as context:
345+
self.cfg.update_config('invalid_key', 1234)
346+
self.assertEqual(str(context.exception), "Unknown configuration key: invalid_key")
347+
348+
@patch('hostcfgd.subprocess.run')
349+
def test_load_config_invalid_json(self, mock_run):
350+
invalid_config_data = "{invalid_json}"
351+
with self.assertRaises(ValueError) as context:
352+
self.cfg.load_config(invalid_config_data)
353+
self.assertEqual(str(context.exception), "Invalid JSON format for configuration data")
332354

333355

334356
class TestDnsHandler:

0 commit comments

Comments
 (0)