Skip to content

Commit 61e0e81

Browse files
authored
Added platform plugin support in load_minigraph (#2808)
Added platform plugin hook to execute platform script after minigraph config is loaded in config db and before starting the services.
1 parent d4355a9 commit 61e0e81

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

config/main.py

+11
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,17 @@ def load_minigraph(db, no_service_restart, traffic_shift_away, override_config,
17551755
raise click.Abort()
17561756
override_config_by(golden_config_path)
17571757

1758+
# Invoke platform script if available before starting the services
1759+
platform_path, _ = device_info.get_paths_to_platform_and_hwsku_dirs()
1760+
platform_mg_plugin = platform_path + '/plugins/platform_mg_post_check'
1761+
if os.path.isfile(platform_mg_plugin):
1762+
click.echo("Running Platform plugin ............!")
1763+
proc = subprocess.Popen([platform_mg_plugin], text=True, stdout=subprocess.PIPE)
1764+
proc.communicate()
1765+
if proc.returncode != 0:
1766+
click.echo("Platform plugin failed! retruncode {}".format(proc.returncode))
1767+
raise click.Abort()
1768+
17581769
# We first run "systemctl reset-failed" to remove the "failed"
17591770
# status from all services before we attempt to restart them
17601771
if not no_service_restart:

tests/config_test.py

+53
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
# Config Reload input Path
3737
mock_db_path = os.path.join(test_path, "config_reload_input")
3838

39+
# Load minigraph input Path
40+
load_minigraph_input_path = os.path.join(test_path, "load_minigraph_input")
41+
load_minigraph_platform_path = os.path.join(load_minigraph_input_path, "platform")
42+
load_minigraph_platform_false_path = os.path.join(load_minigraph_input_path, "platform_false")
3943

4044
load_minigraph_command_output="""\
4145
Stopping SONiC target ...
@@ -47,6 +51,17 @@
4751
Please note setting loaded from minigraph will be lost after system reboot. To preserve setting, run `config save`.
4852
"""
4953

54+
load_minigraph_platform_plugin_command_output="""\
55+
Stopping SONiC target ...
56+
Running command: /usr/local/bin/sonic-cfggen -H -m --write-to-db
57+
Running command: config qos reload --no-dynamic-buffer --no-delay
58+
Running command: pfcwd start_default
59+
Running Platform plugin ............!
60+
Restarting SONiC target ...
61+
Reloading Monit configuration ...
62+
Please note setting loaded from minigraph will be lost after system reboot. To preserve setting, run `config save`.
63+
"""
64+
5065
load_mgmt_config_command_ipv4_only_output="""\
5166
Running command: /usr/local/bin/sonic-cfggen -M device_desc.xml --write-to-db
5267
parse dummy device_desc.xml
@@ -253,6 +268,7 @@ def setup_class(cls):
253268
import config.main
254269
importlib.reload(config.main)
255270

271+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
256272
def test_load_minigraph(self, get_cmd_module, setup_single_broadcom_asic):
257273
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect)) as mock_run_command:
258274
(config, show) = get_cmd_module
@@ -267,6 +283,35 @@ def test_load_minigraph(self, get_cmd_module, setup_single_broadcom_asic):
267283
mock_run_command.assert_any_call('systemctl reset-failed swss')
268284
assert mock_run_command.call_count == 8
269285

286+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=(load_minigraph_platform_path, None)))
287+
def test_load_minigraph_platform_plugin(self, get_cmd_module, setup_single_broadcom_asic):
288+
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect)) as mock_run_command:
289+
(config, show) = get_cmd_module
290+
runner = CliRunner()
291+
result = runner.invoke(config.config.commands["load_minigraph"], ["-y"])
292+
print(result.exit_code)
293+
print(result.output)
294+
traceback.print_tb(result.exc_info[2])
295+
assert result.exit_code == 0
296+
assert "\n".join([l.rstrip() for l in result.output.split('\n')]) == load_minigraph_platform_plugin_command_output
297+
# Verify "systemctl reset-failed" is called for services under sonic.target
298+
mock_run_command.assert_any_call('systemctl reset-failed swss')
299+
assert mock_run_command.call_count == 8
300+
301+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=(load_minigraph_platform_false_path, None)))
302+
def test_load_minigraph_platform_plugin_fail(self, get_cmd_module, setup_single_broadcom_asic):
303+
print(load_minigraph_platform_false_path)
304+
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect)) as mock_run_command:
305+
(config, show) = get_cmd_module
306+
runner = CliRunner()
307+
result = runner.invoke(config.config.commands["load_minigraph"], ["-y"])
308+
print(result.exit_code)
309+
print(result.output)
310+
traceback.print_tb(result.exc_info[2])
311+
assert result.exit_code != 0
312+
assert "Platform plugin failed" in result.output
313+
314+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
270315
def test_load_minigraph_with_port_config_bad_format(self, get_cmd_module, setup_single_broadcom_asic):
271316
with mock.patch(
272317
"utilities_common.cli.run_command",
@@ -281,6 +326,7 @@ def test_load_minigraph_with_port_config_bad_format(self, get_cmd_module, setup_
281326
port_config = [{}]
282327
self.check_port_config(None, config, port_config, "Failed to load port_config.json, Error: Bad format: PORT table not exists")
283328

329+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
284330
def test_load_minigraph_with_port_config_inconsistent_port(self, get_cmd_module, setup_single_broadcom_asic):
285331
with mock.patch(
286332
"utilities_common.cli.run_command",
@@ -292,6 +338,7 @@ def test_load_minigraph_with_port_config_inconsistent_port(self, get_cmd_module,
292338
port_config = [{"PORT": {"Eth1": {"admin_status": "up"}}}]
293339
self.check_port_config(db, config, port_config, "Failed to load port_config.json, Error: Port Eth1 is not defined in current device")
294340

341+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
295342
def test_load_minigraph_with_port_config(self, get_cmd_module, setup_single_broadcom_asic):
296343
with mock.patch(
297344
"utilities_common.cli.run_command",
@@ -309,6 +356,7 @@ def test_load_minigraph_with_port_config(self, get_cmd_module, setup_single_broa
309356
port_config = [{"PORT": {"Ethernet0": {"admin_status": "up"}}}]
310357
self.check_port_config(db, config, port_config, "config interface startup Ethernet0")
311358

359+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
312360
def check_port_config(self, db, config, port_config, expected_output):
313361
def read_json_file_side_effect(filename):
314362
return port_config
@@ -323,6 +371,7 @@ def is_file_side_effect(filename):
323371
assert result.exit_code == 0
324372
assert expected_output in result.output
325373

374+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
326375
def test_load_minigraph_with_non_exist_golden_config_path(self, get_cmd_module):
327376
def is_file_side_effect(filename):
328377
return True if 'golden_config' in filename else False
@@ -334,6 +383,7 @@ def is_file_side_effect(filename):
334383
assert result.exit_code != 0
335384
assert "Cannot find 'non_exist.json'" in result.output
336385

386+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
337387
def test_load_minigraph_with_specified_golden_config_path(self, get_cmd_module):
338388
def is_file_side_effect(filename):
339389
return True if 'golden_config' in filename else False
@@ -345,6 +395,7 @@ def is_file_side_effect(filename):
345395
assert result.exit_code == 0
346396
assert "config override-config-table golden_config.json" in result.output
347397

398+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
348399
def test_load_minigraph_with_default_golden_config_path(self, get_cmd_module):
349400
def is_file_side_effect(filename):
350401
return True if 'golden_config' in filename else False
@@ -356,6 +407,7 @@ def is_file_side_effect(filename):
356407
assert result.exit_code == 0
357408
assert "config override-config-table /etc/sonic/golden_config_db.json" in result.output
358409

410+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
359411
def test_load_minigraph_with_traffic_shift_away(self, get_cmd_module):
360412
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect)) as mock_run_command:
361413
(config, show) = get_cmd_module
@@ -367,6 +419,7 @@ def test_load_minigraph_with_traffic_shift_away(self, get_cmd_module):
367419
assert result.exit_code == 0
368420
assert "TSA" in result.output
369421

422+
@mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None)))
370423
def test_load_minigraph_with_traffic_shift_away_with_golden_config(self, get_cmd_module):
371424
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect)) as mock_run_command:
372425
def is_file_side_effect(filename):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo "Do Nothing!"
4+
exit 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo "Do Nothing!"
4+
exit 1

0 commit comments

Comments
 (0)