Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
4e16175
Added memory_statistics cfg
KanzaLatif Aug 8, 2024
d0b3fe0
Added the test_event file for memory_statistics
kanza-latif Aug 8, 2024
e2f619f
Add MemoryStatsCfg class to manage memory statistics configuration
Arham-Nasir Aug 14, 2024
017b959
madified memory statistics class
kanza-latif Aug 30, 2024
4dac17f
added apply_configurations function
kanza-latif Sep 5, 2024
f581541
updated test case file and the memory_statistics class
kanza-latif Sep 9, 2024
0dc74c8
resolved all the errors
kanza-latif Sep 10, 2024
dcf37a3
resolved function error
kanza-latif Sep 10, 2024
6c5964b
updated hostcfgd
kanza-latif Sep 10, 2024
c7fd2e6
resolving errors
kanza-latif Sep 10, 2024
c1740b0
resolved testing error
kanza-latif Sep 10, 2024
a45a57a
resolved error
kanza-latif Sep 11, 2024
77120ce
resolving errors
kanza-latif Sep 11, 2024
da59394
errors resolving
kanza-latif Sep 11, 2024
c8aa989
error
kanza-latif Sep 11, 2024
3fb4958
resolved error
kanza-latif Sep 11, 2024
4e25cfb
resolving erors
kanza-latif Sep 11, 2024
3ef484c
errors
kanza-latif Sep 12, 2024
3f8d9de
resolved errors
kanza-latif Sep 12, 2024
febf2a0
resolving errors in the test file
kanza-latif Sep 12, 2024
7e76786
taking it a few commits back to resolve errors
kanza-latif Sep 13, 2024
beac5a5
removed pycairofile
kanza-latif Sep 13, 2024
bbdfee9
chaged hostcfgd
kanza-latif Sep 13, 2024
2c1f0cf
errors resolving
kanza-latif Sep 13, 2024
b887226
errors
kanza-latif Sep 16, 2024
fc7645a
Merge branch 'master' into memory_statistics
kanza-latif Sep 16, 2024
f42d768
resolves type errors and key errors
Arham-Nasir Sep 17, 2024
78ed39c
modified the hostcfgd
kanza-latif Sep 18, 2024
ce3f215
added the test_vectors file
kanza-latif Sep 18, 2024
efcae92
resolved errors
kanza-latif Sep 19, 2024
db735d5
errors
kanza-latif Sep 19, 2024
1d403ac
changed the name of db table
kanza-latif Sep 20, 2024
0b9698c
added swss common attributes
kanza-latif Sep 20, 2024
a447a1b
added swss common attribute
kanza-latif Sep 24, 2024
7d61447
added swss common attribute
kanza-latif Sep 24, 2024
d3c0ee0
changed swss common
kanza-latif Sep 24, 2024
82aca30
added sighup and sigterm signals
kanza-latif Sep 24, 2024
dc3939d
added pid
kanza-latif Sep 24, 2024
de9c607
changes made
kanza-latif Sep 24, 2024
7251ad8
imported the swss common again
kanza-latif Sep 24, 2024
5a92cc3
Updated the hostcfgd code
Arham-Nasir Sep 24, 2024
fd20479
corrected import
kanza-latif Sep 25, 2024
1bcc1ef
updated the init_data
kanza-latif Sep 25, 2024
7d4834c
printing the swsscommon file
kanza-latif Sep 25, 2024
8287519
updated hostcfgd
kanza-latif Sep 25, 2024
a20427f
updated hostcfgd
kanza-latif Sep 25, 2024
a5182b1
upodated the code
kanza-latif Sep 25, 2024
15a5c6e
upodated the code
kanza-latif Sep 25, 2024
158b103
updated the hostcfgd class
kanza-latif Sep 25, 2024
c740c82
updated vector.py file and hostcfgd
kanza-latif Sep 25, 2024
9c080dc
updated the test file
kanza-latif Sep 25, 2024
b273630
comment code for testing
Arham-Nasir Sep 25, 2024
116fa01
imported the restart_waiter from swsssommon
kanza-latif Sep 26, 2024
e2063f1
removed syntax error
kanza-latif Sep 26, 2024
4fadaf5
import error
kanza-latif Sep 26, 2024
32fa732
import error
kanza-latif Sep 26, 2024
8fe3880
updated the test file
kanza-latif Sep 26, 2024
5bd978b
updated path to config db
kanza-latif Sep 26, 2024
94c797b
errors
kanza-latif Sep 26, 2024
248e672
errors
kanza-latif Sep 26, 2024
bfea2ab
update test cases
Arham-Nasir Sep 26, 2024
f528e06
update test cases
Arham-Nasir Sep 26, 2024
b529983
update test cases
Arham-Nasir Sep 26, 2024
c9fde05
errors
kanza-latif Sep 26, 2024
8ff1832
resoving errors
kanza-latif Sep 26, 2024
929ac18
changed the test file
kanza-latif Sep 26, 2024
e77850f
chnaged test file
kanza-latif Sep 26, 2024
17f295e
changed the path of db
kanza-latif Sep 26, 2024
b899dfd
undid a few things
kanza-latif Sep 26, 2024
a76deb7
errorss
kanza-latif Sep 26, 2024
3fc60e3
chacking the code
kanza-latif Sep 26, 2024
38e869b
updated the hostcfgd file
kanza-latif Sep 26, 2024
1227075
Merge branch 'master' into memory_statistics
Arham-Nasir Oct 30, 2024
dc04e8a
update hostcfgd code
Arham-Nasir Oct 30, 2024
16abf44
update hostcfgd code
Arham-Nasir Oct 30, 2024
de51fd7
update hostcfgd code
Arham-Nasir Oct 30, 2024
d705e06
update hostcfgd
Arham-Nasir Nov 11, 2024
ff69f7c
update testcases
Arham-Nasir Nov 11, 2024
6622d11
update testcases
Arham-Nasir Nov 11, 2024
329195a
update testcases
Arham-Nasir Nov 11, 2024
8ca20ae
update testcases
Arham-Nasir Nov 11, 2024
7daab75
update testcases
Arham-Nasir Nov 11, 2024
b82b89c
update hostcfgd
Arham-Nasir Nov 12, 2024
89075f8
update testcases
Arham-Nasir Nov 12, 2024
91e3fa5
update testcases
Arham-Nasir Nov 12, 2024
4573619
update testcases
Arham-Nasir Nov 12, 2024
d126612
update testcases
Arham-Nasir Nov 12, 2024
8718d31
update testcases
Arham-Nasir Nov 12, 2024
800ea27
update hostconfig daemon
Arham-Nasir Nov 14, 2024
75b99ef
update hostconfig daemon
Arham-Nasir Nov 14, 2024
9ddcb98
update hostconfig daemon
Arham-Nasir Nov 14, 2024
64c0fcd
update test cases
Arham-Nasir Nov 14, 2024
5c78fa1
update hostcfgd_test file
Arham-Nasir Nov 15, 2024
e75bd8d
update hostcfgd_test file
Arham-Nasir Nov 15, 2024
759f3da
update hostcfgd_test file
Arham-Nasir Nov 15, 2024
755d480
update hostcfgd test file
Arham-Nasir Nov 16, 2024
fca6d53
update hostcfgd test file
Arham-Nasir Nov 16, 2024
5a03fbf
update hostcfgd test file
Arham-Nasir Nov 16, 2024
2d1704c
update hostcfgd test file
Arham-Nasir Nov 16, 2024
de51001
update hostcfgd test file
Arham-Nasir Nov 16, 2024
a7c757a
update test cases
Arham-Nasir Nov 16, 2024
d0acb34
update test cases
Arham-Nasir Nov 16, 2024
40421de
update test cases
Arham-Nasir Nov 16, 2024
3d6c1be
update test cases
Arham-Nasir Nov 16, 2024
4486515
update test cases
Arham-Nasir Nov 17, 2024
d502eae
update test cases
Arham-Nasir Nov 17, 2024
b2b3cc6
update test cases
Arham-Nasir Nov 17, 2024
318206e
update test cases
Arham-Nasir Nov 17, 2024
2256644
update test cases
Arham-Nasir Nov 17, 2024
d01c98b
update test cases
Arham-Nasir Nov 17, 2024
3463373
update test cases
Arham-Nasir Nov 17, 2024
3d95d29
update test cases
Arham-Nasir Nov 17, 2024
fdf8e8a
update test cases
Arham-Nasir Nov 17, 2024
14ecdb0
update test cases
Arham-Nasir Nov 17, 2024
f2a19b8
update test cases
Arham-Nasir Nov 17, 2024
90e51b3
update test cases
Arham-Nasir Nov 17, 2024
152a649
update test cases
Arham-Nasir Nov 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 192 additions & 4 deletions scripts/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import syslog
import signal
import re
import jinja2
import time
import json
import psutil
from shutil import copy2
from datetime import datetime
from sonic_py_common import device_info
Expand Down Expand Up @@ -1716,7 +1718,179 @@ class FipsCfg(object):
syslog.syslog(syslog.LOG_INFO, f'FipsCfg: update the FIPS enforce option {self.enforce}.')
loader.set_fips(image, self.enforce)

class MemoryStatisticsCfg:
"""
The MemoryStatisticsCfg class manages the configuration updates for the MemoryStatisticsDaemon, a daemon
responsible for collecting memory usage statistics. It monitors configuration changes in ConfigDB and, based
on those updates, performs actions such as restarting, shutting down, or reloading the daemon.

Attributes:
VALID_KEYS (list): List of valid configuration keys ("enabled", "sampling_interval", "retention_period").
PID_FILE_PATH (str): Path where the daemon’s process ID (PID) is stored.
DAEMON_EXEC_PATH (str): Path to the executable file of the memory statistics daemon.
DAEMON_PROCESS_NAME (str): Name of the daemon process used for validation.
"""
VALID_KEYS = ["enabled", "sampling_interval", "retention_period"]
PID_FILE_PATH = '/var/run/memory_statistics_daemon.pid'
DAEMON_EXEC_PATH = '/usr/bin/memory_statistics_service.py'
DAEMON_PROCESS_NAME = 'memory_statistics_service.py'

def __init__(self, config_db):
"""
Initialize MemoryStatisticsCfg with a configuration database.

Parameters:
config_db (object): Instance of the configuration database (ConfigDB) used to retrieve and
apply configuration changes.
"""
self.cache = {
"enabled": "false",
"sampling_interval": "5",
"retention_period": "15"
}
self.config_db = config_db

def load(self, memory_statistics_config: dict):
"""
Load the initial memory statistics configuration from a provided dictionary.

Parameters:
memory_statistics_config (dict): Dictionary containing the initial configuration values.
"""
syslog.syslog(syslog.LOG_INFO, 'MemoryStatisticsCfg: Loading initial configuration')

if not memory_statistics_config:
memory_statistics_config = {}

for key, value in memory_statistics_config.items():
if key not in self.VALID_KEYS:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Invalid key '{key}' in initial configuration.")
continue
self.memory_statistics_update(key, value)

def memory_statistics_update(self, key, data):
"""
Handles updates for each configuration setting, validates the data, and updates the cache if the value changes.

Parameters:
key (str): Configuration key, e.g., "enabled", "sampling_interval", or "retention_period".
data (str): The new value for the configuration key.
"""
if key not in self.VALID_KEYS:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Invalid key '{key}' received.")
return

data = str(data)

if key in ["retention_period", "sampling_interval"] and (not data.isdigit() or int(data) <= 0):
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Invalid value '{data}' for key '{key}'. Must be a positive integer.")
return

if data != self.cache.get(key):
syslog.syslog(syslog.LOG_INFO, f"MemoryStatisticsCfg: Detected change in '{key}' to '{data}'")

try:
self.apply_setting(key, data)
self.cache[key] = data
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f'MemoryStatisticsCfg: Failed to manage MemoryStatisticsDaemon: {e}')

def apply_setting(self, key, data):
"""
Apply the setting based on the key. If "enabled" is set to true or false, start or stop the daemon.
For other keys, reload the daemon configuration.

Parameters:
key (str): The specific configuration setting being updated.
data (str): The value for the setting.
"""
try:
if key == "enabled":
if data.lower() == "true":
self.restart_memory_statistics()
else:
self.shutdown_memory_statistics()
else:
self.reload_memory_statistics()
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: {type(e).__name__} in apply_setting() for key '{key}': {e}")

def restart_memory_statistics(self):
"""Restarts the memory statistics daemon by first shutting it down (if running) and then starting it again."""
try:
self.shutdown_memory_statistics()
time.sleep(1)
syslog.syslog(syslog.LOG_INFO, "MemoryStatisticsCfg: Starting MemoryStatisticsDaemon")
subprocess.Popen([self.DAEMON_EXEC_PATH])
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Failed to start MemoryStatisticsDaemon: {e}")

def reload_memory_statistics(self):
"""Sends a SIGHUP signal to the daemon to reload its configuration without restarting."""
pid = self.get_memory_statistics_pid()
if pid:
try:
os.kill(pid, signal.SIGHUP)
syslog.syslog(syslog.LOG_INFO, "MemoryStatisticsCfg: Sent SIGHUP to reload daemon configuration")
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Failed to reload MemoryStatisticsDaemon: {e}")

def shutdown_memory_statistics(self):
"""Sends a SIGTERM signal to gracefully shut down the daemon."""
pid = self.get_memory_statistics_pid()
if pid:
try:
os.kill(pid, signal.SIGTERM)
syslog.syslog(syslog.LOG_INFO, "MemoryStatisticsCfg: Sent SIGTERM to stop MemoryStatisticsDaemon")
self.wait_for_shutdown(pid)
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Failed to shutdown MemoryStatisticsDaemon: {e}")

def wait_for_shutdown(self, pid, timeout=10):
"""
Waits for the daemon process to terminate gracefully within a given timeout.

Parameters:
pid (int): Process ID of the daemon to shut down.
timeout (int): Maximum wait time in seconds for the process to terminate (default is 10 seconds).
"""
try:
process = psutil.Process(pid)
process.wait(timeout=timeout)
syslog.syslog(syslog.LOG_INFO, "MemoryStatisticsCfg: MemoryStatisticsDaemon stopped gracefully")
except psutil.TimeoutExpired:
syslog.syslog(syslog.LOG_WARNING, f"MemoryStatisticsCfg: Timed out while waiting for daemon (PID {pid}) to shut down.")
except psutil.NoSuchProcess:
syslog.syslog(syslog.LOG_WARNING, "MemoryStatisticsCfg: MemoryStatisticsDaemon process not found.")
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Exception in wait_for_shutdown(): {e}")

def get_memory_statistics_pid(self):
"""
Retrieves the PID of the currently running daemon from the PID file, verifying it matches the expected daemon.

Returns:
int or None: Returns the PID if the process is running and matches the expected daemon; otherwise, returns None.
"""
try:
with open(self.PID_FILE_PATH, 'r') as pid_file:
pid = int(pid_file.read().strip())
if psutil.pid_exists(pid):
process = psutil.Process(pid)
if process.name() == self.DAEMON_PROCESS_NAME:
return pid
else:
syslog.syslog(syslog.LOG_WARNING, f"MemoryStatisticsCfg: PID {pid} does not correspond to {self.DAEMON_PROCESS_NAME}.")
else:
syslog.syslog(syslog.LOG_WARNING, "MemoryStatisticsCfg: PID does not exist.")
except FileNotFoundError:
syslog.syslog(syslog.LOG_WARNING, "MemoryStatisticsCfg: PID file not found. Daemon might not be running.")
except ValueError:
syslog.syslog(syslog.LOG_ERR, "MemoryStatisticsCfg: PID file contents invalid.")
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: {type(e).__name__} failed to retrieve MemoryStatisticsDaemon PID: {e}")
return None

class SerialConsoleCfg:

def __init__(self):
Expand Down Expand Up @@ -1748,7 +1922,6 @@ class SerialConsoleCfg:

return


class BannerCfg(object):
"""
Banner Config Daemon
Expand Down Expand Up @@ -1826,7 +1999,6 @@ class BannerCfg(object):
for k,v in data.items():
self.cache[k] = v


class HostConfigDaemon:
def __init__(self):
self.state_db_conn = DBConnector(STATE_DB, 0)
Expand All @@ -1842,6 +2014,9 @@ class HostConfigDaemon:
# Initialize KDump Config and set the config to default if nothing is provided
self.kdumpCfg = KdumpCfg(self.config_db)

# Initialize MemoryStatisticsCfg
self.memorystatisticscfg = MemoryStatisticsCfg(self.config_db)

# Initialize IpTables
self.iptables = Iptables()

Expand Down Expand Up @@ -1896,6 +2071,7 @@ class HostConfigDaemon:
kdump = init_data['KDUMP']
passwh = init_data['PASSW_HARDENING']
ssh_server = init_data['SSH_SERVER']
memory_statistics = init_data["MEMORY_STATISTICS"]
dev_meta = init_data.get(swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, {})
mgmt_ifc = init_data.get(swsscommon.CFG_MGMT_INTERFACE_TABLE_NAME, {})
mgmt_vrf = init_data.get(swsscommon.CFG_MGMT_VRF_CONFIG_TABLE_NAME, {})
Expand All @@ -1912,6 +2088,7 @@ class HostConfigDaemon:
self.aaacfg.load(aaa, tacacs_global, tacacs_server, radius_global, radius_server, ldap_global, ldap_server)
self.iptables.load(lpbk_table)
self.kdumpCfg.load(kdump)
self.memorystatisticscfg.load(memory_statistics)
self.passwcfg.load(passwh)
self.sshscfg.load(ssh_server)
self.devmetacfg.load(dev_meta)
Expand Down Expand Up @@ -2043,6 +2220,14 @@ class HostConfigDaemon:
syslog.syslog(syslog.LOG_INFO, 'Kdump handler...')
self.kdumpCfg.kdump_update(key, data)

def memory_statistics_handler(self, key, op, data):
syslog.syslog(syslog.LOG_INFO, 'Memory_Statistics handler...')
try:
self.memorystatisticscfg.memory_statistics_update(key, data)
except Exception as e:
syslog.syslog(syslog.LOG_ERR, f"MemoryStatisticsCfg: Error while handling memory statistics update: {e}")


def device_metadata_handler(self, key, op, data):
syslog.syslog(syslog.LOG_INFO, 'DeviceMeta handler...')
self.devmetacfg.hostname_update(data)
Expand Down Expand Up @@ -2099,6 +2284,7 @@ class HostConfigDaemon:
return callback

self.config_db.subscribe('KDUMP', make_callback(self.kdump_handler))
self.config_db.subscribe('MEMORY_STATISTICS',make_callback(self.memory_statistics_handler))
# Handle AAA, TACACS and RADIUS related tables
self.config_db.subscribe('AAA', make_callback(self.aaa_handler))
self.config_db.subscribe('TACPLUS', make_callback(self.tacacs_global_handler))
Expand All @@ -2123,6 +2309,9 @@ class HostConfigDaemon:
# Handle DEVICE_MEATADATA changes
self.config_db.subscribe(swsscommon.CFG_DEVICE_METADATA_TABLE_NAME,
make_callback(self.device_metadata_handler))

# self.config_db.subscribe(swsscommon.CFG_MEMORY_STATISTICS_TABLE_NAME,
# make_callback(self.memory_statistics_handler))

# Handle MGMT_VRF_CONFIG changes
self.config_db.subscribe(swsscommon.CFG_MGMT_VRF_CONFIG_TABLE_NAME,
Expand Down Expand Up @@ -2169,5 +2358,4 @@ def main():
daemon.start()

if __name__ == "__main__":
main()

main()
Loading
Loading