Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
47 changes: 45 additions & 2 deletions src/usr/lib/ztp/ztp-engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,27 @@ def signal_handler(signum, frame):

sys.exit(0)

def get_ntp_service_name():
'''!
Detect which NTP service is active on the system.
Checks in priority order: chrony, ntp

Returns:
str: Name of the active NTP service, or None if none found
'''
ntp_services = ['chrony', 'ntp']
for service in ntp_services:
try:
rc = runCommand('systemctl is-active --quiet ' + service, capture_stdout=False)
if rc == 0:
logger.info('Detected NTP service: %s' % service)
return service
except:
continue

logger.warning('No active NTP service detected (ntp/chrony)')
return None

class ZTPEngine():
'''!
\brief This class performs core functions of ZTP service.
Expand Down Expand Up @@ -814,6 +835,28 @@ def __forceRestartDiscovery(self, msg):
# Restart link-scan
self.__intf_state = dict()

def __restart_network_services(self):
'''!
Restart interfaces-config while rebinding the active NTP service, if any.
'''
ntp_service = get_ntp_service_name()

if ntp_service:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this behavior be handled by interfaces-config or systemd service dependency instead of ZTP? ZTP should ideally not manage unrelated service lifecycle.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 840e0de. I kept this scoped to ZTP because this is the code path explicitly restarting interfaces-config during discovery/resume/remove. chrony.service already has After=interfaces-config.service for startup ordering, but that does not restart/rebind chrony when ZTP later runs systemctl restart interfaces-config. Adding reverse ordering/dependencies from interfaces-config back to NTP/chrony risks an ordering cycle, so I did not alter the systemd unit dependencies in this PR.

logger.info('Stopping %s service...' % ntp_service)
runCommand('systemctl stop ' + ntp_service, capture_stdout=False)

try:
logger.info('Restarting interfaces-config service...')
rc = runCommand('systemctl restart interfaces-config', capture_stdout=False)
if rc != 0:
logger.warning('interfaces-config restart failed with return code %d' % rc)
return rc
finally:
if ntp_service:
logger.info('Starting %s service...' % ntp_service)
runCommand('systemctl start ' + ntp_service, capture_stdout=False)
logger.info('%s service restarted successfully.' % ntp_service)

def executeLoop(self, test_mode=False):
'''!
ZTP service loop which peforms provisioning data discovery and initiates processing.
Expand Down Expand Up @@ -884,7 +927,7 @@ def executeLoop(self, test_mode=False):
if self.__link_scan():
updateActivity('Restarting network discovery after link scan')
logger.info('Restarting network discovery after link scan.')
runCommand('systemctl restart interfaces-config', capture_stdout=False)
self.__restart_network_services()
logger.info('Restarted network discovery after link scan.')
_start_time = time.time()
continue
Expand All @@ -900,7 +943,7 @@ def executeLoop(self, test_mode=False):
# Remove existing leases to source new provisioning data
self.__cleanup_dhcp_leases()
logger.info('Restarting network discovery.')
runCommand('systemctl restart interfaces-config', capture_stdout=False)
self.__restart_network_services()
logger.info('Restarted network discovery.')
_start_time = time.time()
continue
Expand Down
43 changes: 38 additions & 5 deletions src/usr/lib/ztp/ztp-profile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,42 @@ PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`)
HW_KEY=${PRESET[0]}

# Function to detect which NTP service is active
# Different SONiC releases use: ntp or chrony
get_ntp_service() {
for service in chrony ntp; do
if systemctl is-active --quiet "$service"; then
echo "$service"
return 0
fi
done
return 1
}

restart_interfaces_config_with_ntp() {
local ntp_service
local rc

ntp_service=$(get_ntp_service)
if [ -n "$ntp_service" ]; then
echo "Stopping $ntp_service."
updateActivity "Stopping $ntp_service"
systemctl stop "$ntp_service"
fi

echo "Restarting interfaces-config."
updateActivity "Restarting interfaces-config"
systemctl restart interfaces-config
rc=$?

if [ -n "$ntp_service" ]; then
systemctl start "$ntp_service"
echo "Restarted $ntp_service."
fi

return $rc
}

# Command usage and help
usage()
{
Expand Down Expand Up @@ -221,9 +257,7 @@ if [ "$CMD" = "install" ] ; then
# Restart interface configuration again to pickup newly created interfaces
# to start DHCP discovery
if [ "$(ztp status -c)" = "4:IN-PROGRESS" ]; then
echo "Restarting network configuration."
updateActivity "Restarting network configuration"
systemctl restart interfaces-config
restart_interfaces_config_with_ntp
echo "Restarted network configuration."
fi
fi
Expand Down Expand Up @@ -259,9 +293,8 @@ if [ "$CMD" = "remove" ] ; then
sonic-db-cli CONFIG_DB DEL "ZTP|mode" > /dev/null
fi

updateActivity "Restarting network configuration"
# Restart interface configuration to stop DHCP
systemctl restart interfaces-config
restart_interfaces_config_with_ntp
fi

# Remove ZTP DHCP policy
Expand Down
Loading