Skip to content

Commit be870a6

Browse files
authored
[config] Exit with non-zero when qos reload fail (sonic-net#3710)
[config] Exit with non-zero when qos reload fail
1 parent ffa66e9 commit be870a6

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

config/main.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ def _wait_until_clear(tables, interval=0.5, timeout=30, verbose=False):
799799

800800

801801
def _clear_qos(delay=False, verbose=False):
802+
status = True
802803
QOS_TABLE_NAMES = [
803804
'PORT_QOS_MAP',
804805
'QUEUE',
@@ -838,7 +839,8 @@ def _clear_qos(delay=False, verbose=False):
838839
device_metadata = config_db.get_entry('DEVICE_METADATA', 'localhost')
839840
# Traditional buffer manager do not remove buffer tables in any case, no need to wait.
840841
timeout = 120 if device_metadata and device_metadata.get('buffer_model') == 'dynamic' else 0
841-
_wait_until_clear(["BUFFER_*_TABLE:*", "BUFFER_*_SET"], interval=0.5, timeout=timeout, verbose=verbose)
842+
status = _wait_until_clear(["BUFFER_*_TABLE:*", "BUFFER_*_SET"], interval=0.5, timeout=timeout, verbose=verbose)
843+
return status
842844

843845
def _get_sonic_generated_services(num_asic):
844846
if not os.path.isfile(SONIC_GENERATED_SERVICE_PATH):
@@ -3183,6 +3185,7 @@ def _update_buffer_calculation_model(config_db, model):
31833185
help="Dry run, writes config to the given file"
31843186
)
31853187
def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose):
3188+
status = True
31863189
"""Reload QoS configuration"""
31873190
if ports:
31883191
log.log_info("'qos reload --ports {}' executing...".format(ports))
@@ -3191,7 +3194,7 @@ def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose)
31913194

31923195
log.log_info("'qos reload' executing...")
31933196
if not dry_run:
3194-
_clear_qos(delay = not no_delay, verbose=verbose)
3197+
status = _clear_qos(delay=not no_delay, verbose=verbose)
31953198

31963199
_, hwsku_path = device_info.get_paths_to_platform_and_hwsku_dirs()
31973200
sonic_version_file = device_info.get_sonic_version_file()
@@ -3274,6 +3277,9 @@ def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose)
32743277
if buffer_model_updated:
32753278
print("Buffer calculation model updated, restarting swss is required to take effect")
32763279

3280+
if not status:
3281+
sys.exit(1)
3282+
32773283
def _qos_update_ports(ctx, ports, dry_run, json_data):
32783284
"""Reload QoS configuration"""
32793285
_, hwsku_path = device_info.get_paths_to_platform_and_hwsku_dirs()

doc/Command-Reference.md

+1
Original file line numberDiff line numberDiff line change
@@ -9653,6 +9653,7 @@ Some of the example QOS configurations that users can modify are given below.
96539653
96549654
In this example, it uses the buffers.json.j2 file and qos.json.j2 file from platform specific folders.
96559655
When there are no changes in the platform specific configutation files, they internally use the file "/usr/share/sonic/templates/buffers_config.j2" and "/usr/share/sonic/templates/qos_config.j2" to generate the configuration.
9656+
When an error occurs, such as "Operation not completed successfully, please save and reload configuration," the system will record the status, after executing all the latter commands, exit with code 1.
96569657
```
96579658
96589659
**config qos reload --ports port_list**

tests/config_test.py

+40
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,46 @@ def test_qos_clear_no_wait(self, _wait_until_clear):
16311631
_clear_qos(True, False)
16321632
_wait_until_clear.assert_called_with(['BUFFER_*_TABLE:*', 'BUFFER_*_SET'], interval=0.5, timeout=0, verbose=False)
16331633

1634+
@mock.patch('config.main._wait_until_clear')
1635+
def test_clear_qos_without_delay(self, mock_wait_until_clear):
1636+
from config.main import _clear_qos
1637+
1638+
status = _clear_qos(False, False)
1639+
mock_wait_until_clear.assert_not_called()
1640+
assert status is True
1641+
1642+
@mock.patch('config.main._wait_until_clear')
1643+
def test_clear_qos_with_delay_returns_true(self, mock_wait_until_clear):
1644+
from config.main import _clear_qos
1645+
mock_wait_until_clear.return_value = True
1646+
1647+
status = _clear_qos(True, False)
1648+
mock_wait_until_clear.assert_called_once()
1649+
assert status is True
1650+
1651+
@mock.patch('config.main._wait_until_clear')
1652+
def test_clear_qos_with_delay_returns_false(self, mock_wait_until_clear):
1653+
from config.main import _clear_qos
1654+
mock_wait_until_clear.return_value = False
1655+
1656+
status = _clear_qos(True, False)
1657+
mock_wait_until_clear.assert_called_once()
1658+
assert status is False
1659+
1660+
@patch('config.main._wait_until_clear')
1661+
def test_qos_reload_not_empty_should_exit(self, mock_wait_until_clear):
1662+
mock_wait_until_clear.return_value = False
1663+
runner = CliRunner()
1664+
output_file = os.path.join(os.sep, "tmp", "qos_config_output.json")
1665+
print("Saving output in {}".format(output_file))
1666+
result = runner.invoke(
1667+
config.config.commands["qos"], ["reload"]
1668+
)
1669+
print(result.exit_code)
1670+
print(result.output)
1671+
# Expect sys.exit(1) when _wait_until_clear returns False
1672+
assert result.exit_code == 1
1673+
16341674
def test_qos_reload_single(
16351675
self, get_cmd_module, setup_qos_mock_apis,
16361676
setup_single_broadcom_asic

0 commit comments

Comments
 (0)