Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ def _wait_until_clear(tables, interval=0.5, timeout=30, verbose=False):


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

def _get_sonic_generated_services(num_asic):
if not os.path.isfile(SONIC_GENERATED_SERVICE_PATH):
Expand Down Expand Up @@ -3161,6 +3163,7 @@ def _update_buffer_calculation_model(config_db, model):
help="Dry run, writes config to the given file"
)
def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose):
status = True
"""Reload QoS configuration"""
if ports:
log.log_info("'qos reload --ports {}' executing...".format(ports))
Expand All @@ -3169,7 +3172,7 @@ def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose)

log.log_info("'qos reload' executing...")
if not dry_run:
_clear_qos(delay = not no_delay, verbose=verbose)
status = _clear_qos(delay=not no_delay, verbose=verbose)

_, hwsku_path = device_info.get_paths_to_platform_and_hwsku_dirs()
sonic_version_file = device_info.get_sonic_version_file()
Expand Down Expand Up @@ -3252,6 +3255,9 @@ def reload(ctx, no_dynamic_buffer, no_delay, dry_run, json_data, ports, verbose)
if buffer_model_updated:
print("Buffer calculation model updated, restarting swss is required to take effect")

if not status:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error log with additional details

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in _wait_until_clear(), it has printed with this error, maybe user can refer to this one😊

  • if not empty and timeout:
    click.echo("Operation not completed successfully, please save and reload configuration.")

sys.exit(1)

def _qos_update_ports(ctx, ports, dry_run, json_data):
"""Reload QoS configuration"""
_, hwsku_path = device_info.get_paths_to_platform_and_hwsku_dirs()
Expand Down
1 change: 1 addition & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -9636,6 +9636,7 @@ Some of the example QOS configurations that users can modify are given below.

In this example, it uses the buffers.json.j2 file and qos.json.j2 file from platform specific folders.
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.
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.
```

**config qos reload --ports port_list**
Expand Down
40 changes: 40 additions & 0 deletions tests/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,46 @@ def test_qos_clear_no_wait(self, _wait_until_clear):
_clear_qos(True, False)
_wait_until_clear.assert_called_with(['BUFFER_*_TABLE:*', 'BUFFER_*_SET'], interval=0.5, timeout=0, verbose=False)

@mock.patch('config.main._wait_until_clear')
def test_clear_qos_without_delay(self, mock_wait_until_clear):
from config.main import _clear_qos

status = _clear_qos(False, False)
mock_wait_until_clear.assert_not_called()
assert status is True

@mock.patch('config.main._wait_until_clear')
def test_clear_qos_with_delay_returns_true(self, mock_wait_until_clear):
from config.main import _clear_qos
mock_wait_until_clear.return_value = True

status = _clear_qos(True, False)
mock_wait_until_clear.assert_called_once()
assert status is True

@mock.patch('config.main._wait_until_clear')
def test_clear_qos_with_delay_returns_false(self, mock_wait_until_clear):
from config.main import _clear_qos
mock_wait_until_clear.return_value = False

status = _clear_qos(True, False)
mock_wait_until_clear.assert_called_once()
assert status is False

@patch('config.main._wait_until_clear')
def test_qos_reload_not_empty_should_exit(self, mock_wait_until_clear):
mock_wait_until_clear.return_value = False
runner = CliRunner()
output_file = os.path.join(os.sep, "tmp", "qos_config_output.json")
print("Saving output in {}".format(output_file))
result = runner.invoke(
config.config.commands["qos"], ["reload"]
)
print(result.exit_code)
print(result.output)
# Expect sys.exit(1) when _wait_until_clear returns False
assert result.exit_code == 1

def test_qos_reload_single(
self, get_cmd_module, setup_qos_mock_apis,
setup_single_broadcom_asic
Expand Down