-
Notifications
You must be signed in to change notification settings - Fork 201
Module graceful shutdown support #567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
0409850
69fc737
52fed94
13ccb54
f80d453
075f9fe
5c76c4f
954d205
dda9062
f736e7b
9dd80f6
9b59745
44b44f7
6ad3a4c
d2c5010
b53413c
d64f1c8
f75f7e2
24c5eaa
3d3c431
337baa1
f2302e8
71668a8
dd3e462
6ea46bc
2b99de1
6f1e7a2
0cdc5eb
258a1e3
bf55d0c
4ffa284
c6e7c20
194010b
14333dc
0e4d7ca
c80fa7c
35c92f2
5211b46
ec98ff3
273ac84
38e93ba
2be697b
d9208ab
0a8610e
a4464a5
97835fd
1eb15ce
46ed271
f72c96d
0197e54
ae65492
937658f
5973578
e9485bf
7cb3872
82a983f
fc9c331
22fdade
c479203
fe70485
05f786f
545457d
8009ca7
55a4c6d
1c862cd
897562f
6c8a306
d2dd8c8
2f8e72d
ee58019
3e1dd0a
61a091b
3c09b88
da94d73
41f05ce
6e0e7cb
ab9680e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,12 @@ | |
| to interact with a module (as used in a modular chassis) SONiC. | ||
| """ | ||
|
|
||
| import os | ||
| import json | ||
| import time | ||
| import errno | ||
| import sys | ||
| import select | ||
| from . import device_base | ||
|
|
||
|
|
||
|
||
|
|
@@ -54,6 +59,11 @@ class ModuleBase(device_base.DeviceBase): | |
| MODULE_REBOOT_DPU = "DPU" | ||
| # Module reboot type to reboot SMART SWITCH | ||
| MODULE_REBOOT_SMARTSWITCH = "SMARTSWITCH" | ||
| # gnoi reboot pipe related | ||
| GNOI_REBOOT_PIPE_PATH = "/host/gnoi_reboot.pipe" | ||
| GNOI_REBOOT_RESPONSE_PIPE_PATH = "/host/gnoi_reboot_response.pipe" | ||
| GNOI_PORT = 50052 | ||
|
||
| GNOI_RESPONSE_TIMEOUT = 60 # seconds | ||
|
||
|
|
||
| def __init__(self): | ||
| # List of ComponentBase-derived objects representing all components | ||
|
|
@@ -163,6 +173,64 @@ def get_oper_status(self): | |
| """ | ||
| raise NotImplementedError | ||
|
|
||
| def pre_shutdown_hook(self): | ||
|
||
| """ | ||
| Initiates a gNOI reboot request for the DPU and waits for a response. | ||
|
|
||
| This method performs the following steps: | ||
| 1. Sends a JSON-formatted reboot request to the gNOI reboot daemon via a named pipe. | ||
| 2. Waits for a response on a designated response pipe, with a timeout of 60 seconds. | ||
|
||
| 3. Parses the response and returns it. | ||
|
|
||
| Returns: | ||
| dict: A dictionary containing the status and message of the reboot operation. | ||
| Possible statuses include 'success', 'error', and 'timeout'. | ||
| """ | ||
| dpu_ip = self.get_midplane_ip() | ||
| msg = { | ||
| "dpu_name": self.name, | ||
| "dpu_ip": dpu_ip, | ||
| "port": GNOI_PORT | ||
| } | ||
|
|
||
| # Send reboot request | ||
| try: | ||
| with open(GNOI_REBOOT_PIPE_PATH, "w") as pipe: | ||
| pipe.write(json.dumps(msg) + "\n") | ||
| except Exception as e: | ||
| sys.stderr.write(f"Failed to send gNOI reboot for {self.name}: {str(e)}\n") | ||
| return {"status": "error", "message": str(e)} | ||
|
|
||
| # Wait for reboot response | ||
| start_time = time.time() | ||
| try: | ||
| # Open the response pipe in non-blocking mode | ||
| fd = os.open(GNOI_REBOOT_RESPONSE_PIPE_PATH, os.O_RDONLY | os.O_NONBLOCK) | ||
| with os.fdopen(fd) as pipe: | ||
| while True: | ||
| # Check if timeout has been reached | ||
| if time.time() - start_time > GNOI_RESPONSE_TIMEOUT: | ||
| sys.stderr.write(f"Timeout waiting for reboot response for {self.name}\n") | ||
| return {"status": "timeout", "message": "No response received within timeout period"} | ||
|
|
||
| # Use select to wait for data with a timeout | ||
| rlist, _, _ = select.select([pipe], [], [], 1) | ||
| if pipe in rlist: | ||
| line = pipe.readline() | ||
| if line: | ||
| try: | ||
| response = json.loads(line.strip()) | ||
| if response.get("dpu_name") == self.name: | ||
| return response | ||
| except json.JSONDecodeError as e: | ||
| sys.stderr.write(f"JSON decode error: {str(e)}\n") | ||
| else: | ||
| # No data read; wait a bit before retrying | ||
| time.sleep(1) | ||
| except Exception as e: | ||
| sys.stderr.write(f"Error reading reboot response for {self.name}: {str(e)}\n") | ||
| return {"status": "error", "message": str(e)} | ||
|
|
||
| def reboot(self, reboot_type): | ||
| """ | ||
| Request to reboot the module | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this unnecessary new line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vvolam Done