Skip to content

Commit 944175b

Browse files
authored
kdump-Remote-SSH-Configurations (#3400)
What I did Added remote kdump functionality using SSH in SONiC. How I did it I added two new commands and two options to configure the kdump remote ssh feature. How to verify it Upon kernel crash, kdump will transfer the crash report files to the ssh server.
1 parent ce51df2 commit 944175b

File tree

5 files changed

+998
-55
lines changed

5 files changed

+998
-55
lines changed

config/kdump.py

Lines changed: 181 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import sys
2-
32
import click
3+
import os
44
from utilities_common.cli import AbbreviationGroup, pass_db
5-
6-
5+
from ipaddress import ip_address, AddressValueError
6+
import re
77
#
88
# 'kdump' group ('sudo config kdump ...')
99
#
10+
1011
@click.group(cls=AbbreviationGroup, name="kdump")
1112
def kdump():
1213
"""Configure the KDUMP mechanism"""
1314
pass
1415

15-
1616
def check_kdump_table_existence(kdump_table):
1717
"""Checks whether the 'KDUMP' table is configured in Config DB.
1818
@@ -32,40 +32,46 @@ def check_kdump_table_existence(kdump_table):
3232
sys.exit(2)
3333

3434

35+
def echo_reboot_warning():
36+
"""Prints the warning message about reboot requirements."""
37+
click.echo("KDUMP configuration changes may require a reboot to take effect.")
38+
click.echo("Save SONiC configuration using 'config save' before issuing the reboot command.")
3539
#
3640
# 'disable' command ('sudo config kdump disable')
3741
#
38-
@kdump.command(name="disable", short_help="Disable the KDUMP mechanism")
42+
43+
44+
@kdump.command(name="disable", help="Disable the KDUMP mechanism")
3945
@pass_db
4046
def kdump_disable(db):
4147
"""Disable the KDUMP mechanism"""
4248
kdump_table = db.cfgdb.get_table("KDUMP")
4349
check_kdump_table_existence(kdump_table)
4450

4551
db.cfgdb.mod_entry("KDUMP", "config", {"enabled": "false"})
46-
click.echo("KDUMP configuration changes may require a reboot to take effect.")
47-
click.echo("Save SONiC configuration using 'config save' before issuing the reboot command.")
48-
52+
echo_reboot_warning()
4953

5054
#
5155
# 'enable' command ('sudo config kdump enable')
5256
#
53-
@kdump.command(name="enable", short_help="Enable the KDUMP mechanism")
57+
58+
59+
@kdump.command(name="enable", help="Enable the KDUMP mechanism")
5460
@pass_db
5561
def kdump_enable(db):
5662
"""Enable the KDUMP mechanism"""
5763
kdump_table = db.cfgdb.get_table("KDUMP")
5864
check_kdump_table_existence(kdump_table)
5965

6066
db.cfgdb.mod_entry("KDUMP", "config", {"enabled": "true"})
61-
click.echo("KDUMP configuration changes may require a reboot to take effect.")
62-
click.echo("Save SONiC configuration using 'config save' before issuing the reboot command.")
63-
67+
echo_reboot_warning()
6468

6569
#
6670
# 'memory' command ('sudo config kdump memory ...')
6771
#
68-
@kdump.command(name="memory", short_help="Configure the memory for KDUMP mechanism")
72+
73+
74+
@kdump.command(name="memory", help="Configure the memory for KDUMP mechanism")
6975
@click.argument('kdump_memory', metavar='<kdump_memory>', required=True)
7076
@pass_db
7177
def kdump_memory(db, kdump_memory):
@@ -74,14 +80,14 @@ def kdump_memory(db, kdump_memory):
7480
check_kdump_table_existence(kdump_table)
7581

7682
db.cfgdb.mod_entry("KDUMP", "config", {"memory": kdump_memory})
77-
click.echo("KDUMP configuration changes may require a reboot to take effect.")
78-
click.echo("Save SONiC configuration using 'config save' before issuing the reboot command.")
79-
83+
echo_reboot_warning()
8084

8185
#
82-
# 'num_dumps' command ('sudo config keump num_dumps ...')
86+
# 'num_dumps' command ('sudo config kdump num_dumps ...')
8387
#
84-
@kdump.command(name="num_dumps", short_help="Configure the maximum dump files of KDUMP mechanism")
88+
89+
90+
@kdump.command(name="num_dumps", help="Configure the maximum dump files of KDUMP mechanism")
8591
@click.argument('kdump_num_dumps', metavar='<kdump_num_dumps>', required=True, type=int)
8692
@pass_db
8793
def kdump_num_dumps(db, kdump_num_dumps):
@@ -90,3 +96,160 @@ def kdump_num_dumps(db, kdump_num_dumps):
9096
check_kdump_table_existence(kdump_table)
9197

9298
db.cfgdb.mod_entry("KDUMP", "config", {"num_dumps": kdump_num_dumps})
99+
echo_reboot_warning()
100+
101+
102+
@kdump.command(name="remote", help="Configure the remote enable/disable for KDUMP mechanism")
103+
@click.argument('action', metavar='<enable/disable>', required=True, type=click.STRING) # Corrected this line
104+
@pass_db
105+
def remote(db, action):
106+
"""Enable or disable remote kdump feature"""
107+
kdump_table = db.cfgdb.get_table("KDUMP")
108+
check_kdump_table_existence(kdump_table)
109+
110+
# Get the current status of the remote feature as string
111+
current_status = kdump_table["config"].get("remote", "false").lower()
112+
113+
if action.lower() == 'enable':
114+
if current_status == "true":
115+
click.echo("Remote kdump feature is already enabled.")
116+
else:
117+
db.cfgdb.mod_entry("KDUMP", "config", {"remote": "true"})
118+
click.echo("Remote kdump feature enabled.")
119+
echo_reboot_warning()
120+
elif action.lower() == 'disable':
121+
if current_status == "false":
122+
click.echo("Remote kdump feature is already disabled.")
123+
else:
124+
db.cfgdb.mod_entry("KDUMP", "config", {"remote": "false"})
125+
click.echo("Remote kdump feature disabled.")
126+
echo_reboot_warning()
127+
else:
128+
click.echo("Invalid action. Use 'enable' or 'disable'.")
129+
130+
131+
@kdump.group(name="add", help="Add configuration items to KDUMP")
132+
def add():
133+
"""Group of commands to add configuration items to KDUMP"""
134+
pass
135+
136+
137+
@add.command(name="ssh_string", help="Add an SSH string to the KDUMP configuration")
138+
@click.argument('ssh_string', metavar='<ssh_key>', required=True)
139+
@pass_db
140+
def add_ssh_key(db, ssh_string):
141+
"""Add an SSH string to KDUMP configuration"""
142+
143+
def is_valid_ssh_key(ssh_string):
144+
"""Validate the SSH key format"""
145+
# Check if it contains username and hostname/IP (format: username@host)
146+
if "@" not in ssh_string:
147+
return "Invalid format. SSH key must be in 'username@host' format."
148+
149+
username, host = ssh_string.split("@", 1)
150+
151+
# Validate username
152+
if not username or not username.isalnum():
153+
return "Invalid username. Ensure it contains only alphanumeric characters."
154+
155+
# Validate host (IP or hostname)
156+
try:
157+
# Check if it's a valid IP address
158+
ip_address(host)
159+
except AddressValueError:
160+
# If not an IP, validate hostname
161+
hostname_regex = r'^[a-zA-Z0-9.-]+$'
162+
if not re.match(hostname_regex, host) or host.startswith('-') or host.endswith('-'):
163+
return "Invalid host. Must be a valid IP or hostname."
164+
165+
return None # Validation successful
166+
167+
kdump_table = db.cfgdb.get_table("KDUMP")
168+
check_kdump_table_existence(kdump_table)
169+
current_status = kdump_table["config"].get("remote", "false").lower()
170+
171+
if current_status == 'false':
172+
click.echo("Remote feature is not enabled. Please enable the remote feature first.")
173+
return
174+
175+
# Validate SSH key
176+
validation_error = is_valid_ssh_key(ssh_string)
177+
if validation_error:
178+
click.echo(f"Error: {validation_error}")
179+
return
180+
181+
# Add or update the 'ssh_key' entry in the KDUMP table
182+
db.cfgdb.mod_entry("KDUMP", "config", {"ssh_string": ssh_string})
183+
click.echo(f"SSH string added to KDUMP configuration: {ssh_string}")
184+
185+
186+
@add.command(name="ssh_path", help="Add an SSH path to the KDUMP configuration")
187+
@click.argument('ssh_path', metavar='<ssh_path>', required=True)
188+
@pass_db
189+
def add_ssh_path(db, ssh_path):
190+
"""Add an SSH path to KDUMP configuration"""
191+
192+
def is_valid_ssh_path(ssh_path):
193+
"""Validate the SSH path"""
194+
# Check if the path is absolute
195+
if not os.path.isabs(ssh_path):
196+
return "Invalid path. SSH path must be an absolute path."
197+
198+
# (Optional) Check if the path exists on the system
199+
if not os.path.exists(ssh_path):
200+
return f"Invalid path. The path '{ssh_path}' does not exist."
201+
202+
return None # Validation successful
203+
204+
kdump_table = db.cfgdb.get_table("KDUMP")
205+
check_kdump_table_existence(kdump_table)
206+
current_status = kdump_table["config"].get("remote", "false").lower()
207+
if current_status == 'false':
208+
click.echo("Remote feature is not enabled. Please enable the remote feature first.")
209+
return
210+
211+
# Validate SSH path
212+
validation_error = is_valid_ssh_path(ssh_path)
213+
if validation_error:
214+
click.echo(f"Error: {validation_error}")
215+
return
216+
217+
# Add or update the 'ssh_path' entry in the KDUMP table
218+
db.cfgdb.mod_entry("KDUMP", "config", {"ssh_path": ssh_path})
219+
click.echo(f"SSH path added to KDUMP configuration: {ssh_path}")
220+
221+
222+
@kdump.group(name="remove", help="remove configuration items to KDUMP")
223+
def remove():
224+
"""Group of commands to remove configuration items to KDUMP"""
225+
pass
226+
227+
228+
@remove.command(name="ssh_string", help="Remove the SSH string from the KDUMP configuration")
229+
@pass_db
230+
def remove_ssh_string(db):
231+
"""Remove the SSH string from KDUMP configuration"""
232+
kdump_table = db.cfgdb.get_table("KDUMP")
233+
check_kdump_table_existence(kdump_table)
234+
235+
# Check if ssh_string exists
236+
if "ssh_string" in kdump_table["config"]:
237+
db.cfgdb.mod_entry("KDUMP", "config", {"ssh_string": None})
238+
click.echo("SSH string removed from KDUMP configuration.")
239+
else:
240+
click.echo("SSH string not found in KDUMP configuration.")
241+
242+
243+
@remove.command(name="ssh_path", help="Remove the SSH path from the KDUMP configuration")
244+
@pass_db
245+
def remove_ssh_path(db):
246+
"""Remove the SSH path from KDUMP configuration"""
247+
kdump_table = db.cfgdb.get_table("KDUMP")
248+
check_kdump_table_existence(kdump_table)
249+
250+
# Check if ssh_string exists
251+
if "ssh_path" in kdump_table["config"]:
252+
db.cfgdb.mod_entry("KDUMP", "config", {"ssh_path": None})
253+
click.echo("SSH path removed from KDUMP configuration.")
254+
else:
255+
click.echo("SSH path not found in KDUMP configuration.")

0 commit comments

Comments
 (0)