Skip to content
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

Support disable/enable syslog rate limit feature #3072

Merged
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
83 changes: 83 additions & 0 deletions config/syslog.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,3 +471,86 @@ def rate_limit_container(db, service_name, interval, burst):
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
syslog_common.service_validator(feature_data, service_name)
syslog_common.save_rate_limit_to_db(db, service_name, interval, burst, log)


@syslog.group(
name="rate-limit-feature",
cls=clicommon.AliasedGroup
)
def rate_limit_feature():
""" Configure syslog rate limit feature """
pass


@rate_limit_feature.command("enable")
@clicommon.pass_db
def enable_rate_limit_feature(db):
""" Enable syslog rate limit feature """
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
for feature_name in feature_data.keys():
click.echo(f'Enabling syslog rate limit feature for {feature_name}')
output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True)
if not output:
click.echo(f'{feature_name} is not running, ignoring...')
continue

output, _ = clicommon.run_command(['docker', 'exec', '-i', feature_name, 'supervisorctl', 'status', 'containercfgd'],
ignore_error=True, return_cmd=True)
if 'no such process' not in output:
click.echo(f'Syslog rate limit feature is already enabled in {feature_name}, ignoring...')
continue

commands = [
['docker', 'cp', '/usr/share/sonic/templates/containercfgd.conf', f'{feature_name}:/etc/supervisor/conf.d/'],
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'reread'],
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'update'],
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'start', 'containercfgd']
]

failed = False
for command in commands:
output, ret = clicommon.run_command(command, return_cmd=True)
if ret != 0:
failed = True
click.echo(f'Enable syslog rate limit feature for {feature_name} failed - {output}')
break

if not failed:
click.echo(f'Enabled syslog rate limit feature for {feature_name}')


@rate_limit_feature.command("disable")
@clicommon.pass_db
def disable_rate_limit_feature(db):
""" Disable syslog rate limit feature """
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
for feature_name in feature_data.keys():
click.echo(f'Disabling syslog rate limit feature for {feature_name}')
output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True)
if not output:
click.echo(f'{feature_name} is not running, ignoring...')
continue

output, _ = clicommon.run_command(['docker', 'exec', '-i', feature_name, 'supervisorctl', 'status', 'containercfgd'],
ignore_error=True, return_cmd=True)
if 'no such process' in output:
click.echo(f'Syslog rate limit feature is already disabled in {feature_name}, ignoring...')
continue

commands = [
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'stop', 'containercfgd'],
['docker', 'exec', '-i', feature_name, 'rm', '-f', '/etc/supervisor/conf.d/containercfgd.conf'],
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'reread'],
['docker', 'exec', '-i', feature_name, 'supervisorctl', 'update']
]
failed = False
for command in commands:
output, ret = clicommon.run_command(command, return_cmd=True)
if ret != 0:
failed = True
click.echo(f'Disable syslog rate limit feature for {feature_name} failed - {output}')
break

if not failed:
click.echo(f'Disabled syslog rate limit feature for {feature_name}')

27 changes: 27 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -10225,6 +10225,33 @@ This command is used to configure syslog rate limit for containers.
admin@sonic:~$ sudo config syslog rate-limit-container bgp --interval 300 --burst 20000
```

**config syslog rate-limit-feature enable**

This command is used to enable syslog rate limit feature.

- Usage:
```
config syslog rate-limit-feature enable
```

- Example:
```
admin@sonic:~$ sudo config syslog rate-limit-feature enable
```

**config syslog rate-limit-feature disable**

This command is used to disable syslog rate limit feature.

- Usage:
```
config syslog rate-limit-feature disable
```

- Example:
```
admin@sonic:~$ sudo config syslog rate-limit-feature disable
```

Go Back To [Beginning of the document](#) or [Beginning of this section](#syslog)

Expand Down
86 changes: 86 additions & 0 deletions tests/syslog_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,89 @@ def test_show_syslog_rate_limit_container_negative(self, subcommand):
logger.debug("\n" + result.output)
logger.debug(result.exit_code)
assert result.exit_code != SUCCESS

@mock.patch('config.syslog.clicommon.run_command')
def test_enable_syslog_rate_limit_feature(self, mock_run):
db = Db()
db.cfgdb.set_entry(FEATURE_TABLE, 'bgp', {SUPPORT_RATE_LIMIT: 'true',
'state': 'enabled'})

runner = CliRunner()

mock_run.return_value = ('no such process', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["enable"], obj=db
)
assert result.exit_code == SUCCESS

# container not run
mock_run.return_value = ('', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["enable"], obj=db
)
assert result.exit_code == SUCCESS

# process already running
mock_run.return_value = ('something', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["enable"], obj=db
)
assert result.exit_code == SUCCESS

# one command fail
def side_effect(*args, **kwargs):
side_effect.call_count += 1
if side_effect.call_count <= 2:
return 'no such process', 0
else:
return '', -1
side_effect.call_count = 0
mock_run.side_effect = side_effect
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["enable"], obj=db
)
assert result.exit_code == SUCCESS


@mock.patch('config.syslog.clicommon.run_command')
def test_disable_syslog_rate_limit_feature(self, mock_run):
db = Db()
db.cfgdb.set_entry(FEATURE_TABLE, 'bgp', {SUPPORT_RATE_LIMIT: 'true',
'state': 'enabled'})

runner = CliRunner()

mock_run.return_value = ('something', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
)
assert result.exit_code == SUCCESS

# container not run
mock_run.return_value = ('', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
)
assert result.exit_code == SUCCESS

# process already stopped
mock_run.return_value = ('no such process', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
)
assert result.exit_code == SUCCESS

# one command fail
def side_effect(*args, **kwargs):
side_effect.call_count += 1
if side_effect.call_count <= 2:
return 'something', 0
else:
return '', -1
side_effect.call_count = 0
mock_run.side_effect = side_effect
result = runner.invoke(
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
)
assert result.exit_code == SUCCESS

Loading