Skip to content

Commit

Permalink
sonic-host-services changes for gNOI Warm Reboot
Browse files Browse the repository at this point in the history
  • Loading branch information
rkavitha-hcl authored and Bibhuprasad Singh committed Feb 27, 2025
1 parent 8773883 commit e60d9f2
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 124 deletions.
47 changes: 26 additions & 21 deletions host_modules/reboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@
MOD_NAME = 'reboot'
# Reboot method in reboot request
# Both enum and string representations are supported
REBOOTMETHOD_COLD_BOOT_VALUES = {1, "COLD"}
REBOOTMETHOD_WARM_BOOT_VALUES = {4, "WARM"}
REBOOTMETHOD_NSF_VALUES = {5, "NSF"}
# Define an Enum for Reboot Methods which are defined as in https://github.com/openconfig/gnoi/blob/main/system/system.pb.go#L27
REBOOT_METHOD_COLD_BOOT_VALUES = {1, "COLD"}
REBOOT_METHOD_HALT_BOOT_VALUES = {3, "HALT"}
REBOOT_METHOD_WARM_BOOT_VALUES = {4, "WARM"}

# Timeout for SONiC Host Service to be killed during reboot
REBOOT_TIMEOUT = 260

EXECUTE_COLD_REBOOT_COMMAND = "sudo reboot"
EXECUTE_NSF_REBOOT_COMMAND = "/etc/init.d/gpins-nsf-boot nsf-reboot"
EXECUTE_HALT_REBOOT_COMMAND = "sudo reboot -p"
EXECUTE_WARM_REBOOT_COMMAND = "sudo warm-reboot"

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -52,30 +54,31 @@ def validate_reboot_request(self, reboot_request):
return 1, "Reboot request must contain a reboot method"

# Check whether reboot method is valid.
rebootmethod = reboot_request["method"]
valid_method = False
for values in [REBOOTMETHOD_COLD_BOOT_VALUES, REBOOTMETHOD_NSF_VALUES]:
if rebootmethod in values:
valid_method = True
if not valid_method:
return 1, "Invalid reboot method: " + str(rebootmethod)
reboot_method = reboot_request["method"]
valid_reboot_method = REBOOT_METHOD_COLD_BOOT_VALUES | REBOOT_METHOD_HALT_BOOT_VALUES | REBOOT_METHOD_WARM_BOOT_VALUES
if reboot_method not in valid_reboot_method:
return 1, "Unsupported reboot method: " + str(reboot_method)

# Check whether delay is non-zero. delay key will not exist in reboot_request if it is zero
if "delay" in reboot_request and reboot_request["delay"] != 0:
return 1, "Delayed reboot is not supported"
return 0, ""

def execute_reboot(self, rebootmethod):
"""Execute reboot and reset reboot_status_flag when reboot fails"""
def execute_reboot(self, reboot_method):
"""Executes reboot command based on the reboot_method initialised
and reset reboot_status_flag when reboot fails."""

if rebootmethod in REBOOTMETHOD_COLD_BOOT_VALUES:
if reboot_method in REBOOT_METHOD_COLD_BOOT_VALUES:
command = EXECUTE_COLD_REBOOT_COMMAND
logger.warning("%s: Issuing cold reboot", MOD_NAME)
elif rebootmethod in REBOOTMETHOD_NSF_VALUES:
command = EXECUTE_NSF_REBOOT_COMMAND
logger.warning("%s: Issuing NSF reboot", MOD_NAME)
elif reboot_method in REBOOT_METHOD_HALT_BOOT_VALUES:
command = EXECUTE_HALT_REBOOT_COMMAND
logger.warning("%s: Issuing halt reboot", MOD_NAME)
elif reboot_method in REBOOT_METHOD_WARM_BOOT_VALUES:
command = EXECUTE_WARM_REBOOT_COMMAND
logger.warning("%s: Issuing WARM reboot", MOD_NAME)
else:
logger.error("%s: Invalid reboot method: %d", MOD_NAME, rebootmethod)
logger.error("%s: Unsupported reboot method: %d", MOD_NAME, reboot_method)
return

rc, stdout, stderr = _run_command(command)
Expand All @@ -85,19 +88,21 @@ def execute_reboot(self, rebootmethod):
"stderr: %s", MOD_NAME, stdout, stderr)
return

"""Wait for 260 seconds for the reboot to complete. Here, we expect that SONiC Host Service
"""Wait for the reboot to complete. Here, we expect that SONiC Host Service
will be killed during this waiting period if the reboot is successful. If this module
is still alive after the below waiting period, we can conclude that the reboot has failed.
Each container can take up to 20 seconds to get killed. In total, there are 10 containers,
and adding a buffer of 1 minute brings up the delay value to be 260 seconds."""
and adding a buffer of 1 minute brings up the delay value."""
time.sleep(REBOOT_TIMEOUT)
# Conclude that the reboot has failed if we reach this point
self.populate_reboot_status_flag()
return

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='as', out_signature='is')

def issue_reboot(self, options):
"""Issues reboot after performing the following steps sequentially:
"""Initializes reboot thorugh RPC based on the reboot flag assigned.
Issues reboot after performing the following steps sequentially:
1. Checks that reboot_status_flag is not set
2. Validates the reboot request
3. Sets the reboot_status_flag
Expand Down
29 changes: 3 additions & 26 deletions host_modules/systemd_service.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
"""Systemd service handler"""

from enum import Enum
from host_modules import host_service
import subprocess

MOD_NAME = 'systemd'
ALLOWED_SERVICES = ['snmp', 'swss', 'dhcp_relay', 'radv', 'restapi', 'lldp', 'sshd', 'pmon', 'rsyslog', 'telemetry']
EXIT_FAILURE = 1

# Define an Enum for Reboot Methods which are defined as in
# https://github.com/openconfig/gnoi/blob/main/system/system.pb.go#L27
class RebootMethod(Enum):
COLD = 1
HALT = 3

class SystemdService(host_service.HostModule):
"""
DBus endpoint that executes the service command
Expand All @@ -32,15 +25,15 @@ def restart_service(self, service):
msg = result.stderr.decode()
if possible_expected_error not in msg:
return result.returncode, msg # Throw error only if unexpected error

msg = ''
cmd = ['/usr/bin/systemctl', 'restart', service]
result = subprocess.run(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode:
msg = result.stderr.decode()

return result.returncode, msg

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='s', out_signature='is')
def stop_service(self, service):
if not service:
Expand All @@ -54,19 +47,3 @@ def stop_service(self, service):
if result.returncode:
msg = result.stderr.decode()
return result.returncode, msg

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='i', out_signature='is')
def execute_reboot(self, rebootmethod):
if rebootmethod == RebootMethod.COLD:
cmd = ['/usr/local/bin/reboot']
elif rebootmethod == RebootMethod.HALT:
cmd = ['/usr/local/bin/reboot','-p']
else:
return EXIT_FAILURE, "{}: Invalid reboot method: {}".format(MOD_NAME, rebootmethod)

result = subprocess.run(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
msg = ''
if result.returncode:
msg = result.stderr.decode()

return result.returncode, msg
2 changes: 1 addition & 1 deletion scripts/sonic-host-server
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def register_dbus():
'config': config_engine.Config('config'),
'gcu': gcu.GCU('gcu'),
'host_service': host_service.HostService('host_service'),
'reboot': reboot.Reboot('reboot'),
'reboot': reboot.Reboot('reboot'),
'showtech': showtech.Showtech('showtech'),
'systemd': systemd_service.SystemdService('systemd'),
'image_service': image_service.ImageService('image_service'),
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
maintainer_email = 'jolevequ@microsoft.com',
packages = [
'host_modules',
'utils',
'utils',
],
scripts = [
'scripts/caclmgrd',
Expand Down
Loading

0 comments on commit e60d9f2

Please sign in to comment.