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

[Logrotate] Add config and show commands #3293

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
77 changes: 77 additions & 0 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7905,5 +7905,82 @@ def notice(db, category_list, max_events, namespace):
handle_asic_sdk_health_suppress(db, 'notice', category_list, max_events, namespace)


#
# 'logrotate' group ('config logrotate ...')
#
@config.group(invoke_without_command=True)
@click.pass_context
@click.argument('file', required=True, type=click.Choice(['syslog', 'debug']))
def logrotate(ctx, file):
"""Configuring logrotate"""
# If invoking subcomand, no need to do anything
if ctx.invoked_subcommand is not None:
return

config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry(swsscommon.CFG_LOGGING_TABLE_NAME, file, None)


@logrotate.command()
@click.pass_context
@click.argument('disk_percentage', metavar='<disk-percentage>',
required=True, type=float)
def disk_percentage(ctx, disk_percentage):
"""Configuring logrotate disk-precentage"""
file = ctx.parent.params.get('file')
if 0 > disk_percentage > 100:
click.echo(f'Disk percentage {disk_percentage} is not in range [0 - 100]')
pass

config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry(swsscommon.CFG_LOGGING_TABLE_NAME, file,
{'disk_percentage': disk_percentage})


@logrotate.command(name='frequency')
@click.pass_context
@click.argument('frequency', metavar='<daily|weekly|monthly|yearly>',
required=True,
type=click.Choice(['daily', 'weekly', 'monthly', 'yearly']))
fastiuk marked this conversation as resolved.
Show resolved Hide resolved
def logrotate_frequency(ctx, frequency):
"""Configuring logrotate rotation frequency"""
file = ctx.parent.params.get('file')
config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry(swsscommon.CFG_LOGGING_TABLE_NAME, file,
{'frequency': frequency})


@logrotate.command()
@click.pass_context
@click.argument('max_number', metavar='<max-number>',
type=click.IntRange(0, 999999), required=True)
def max_number(ctx, max_number):
"""Configuring logrotate max-number of files"""
file = ctx.parent.params.get('file')
config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry(swsscommon.CFG_LOGGING_TABLE_NAME, file,
{'max_number': max_number})


@logrotate.command(name='size')
@click.pass_context
@click.argument('size', metavar='<size>', type=float, required=True)
def logrotate_size(ctx, size):
"""Configuring logrotate size of file"""
file = ctx.parent.params.get('file')
if 0.001 > size > 3500.0:
click.echo(f'Size {size} is not in range [0.001 - 3500.0]')
pass

config_db = ConfigDBConnector()
config_db.connect()
config_db.mod_entry(swsscommon.CFG_LOGGING_TABLE_NAME, file,
{'size': size})


if __name__ == '__main__':
config()
69 changes: 68 additions & 1 deletion doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@
* [Reloading Configuration](#reloading-configuration)
* [Loading Management Configuration](#loading-management-configuration)
* [Saving Configuration to a File for Persistence](#saving-configuration-to-a-file-for-persistence)
* [Loopback Interfaces](#loopback-interfaces)
* [Logrotate](#logrotate)
* [Logrotate config commands](#logrotate-config-commands)
* [Logrotate show command](#logrotate-show-command)
* [Loopback Interfaces](#loopback-interfaces)
* [Loopback show commands](#loopback-show-commands)
* [Loopback config commands](#loopback-config-commands)
* [VRF Configuration](#vrf-configuration)
Expand Down Expand Up @@ -13701,3 +13704,67 @@ Sending 3 magic packet to 11:33:55:77:99:bb via interface Vlan1000
```

For the 4th example, it specifise 2 target MAC addresses and `count` is 3. So it'll send 6 magic packets in total.


# Logrotate Commands
This sub-section explains the list of the configuration options available for logrotate feature.
## Logrotate config commands
- Rotate logs when they surpass a specified percentage of disk
```
admin@sonic:~$ config logrotate disk-percentage <> <>
Usage: config logrotate disk-precentage [OPTIONS] <syslog|debug> <disk-percentage>

Configuring logrotate disk-precentage file <syslog|debug> <disk_percentage>

Options:
-?, -h, --help Show this message and exit.
```
- Log files rotation frequency
```
admin@sonic:~$ config logrotate frequency <syslog|debug> <daily|weekly|monthly|yearly>
Usage: config logrotate frequency [OPTIONS] <syslog|debug> <daily|weekly|monthly|yearly>

Configuring logrotate frequency file <syslog|debug> <frequency>

Options:
-?, -h, --help Show this message and exit.
```
- Max number of log files to keep
```
admin@sonic:~$ config logrotate max-number <syslog|debug> <max-number>
Usage: config logrotate max-number [OPTIONS] <syslog|debug> <max-number>

Configuring logrotate max-number file <syslog|debug> <max_number>

Options:
-?, -h, --help Show this message and exit.
```
- Rotate logs if they grow bigger then size in Mebibytes
```
admin@sonic:~$ config logrotate size <syslog|debug> <size>
Usage: config logrotate size [OPTIONS] <syslog|debug> <size>

Configuring logrotate size file <syslog|debug> <size>

Options:
-h, -?, --help Show this message and exit.
```
## Logrotate show command
- Show logrotate configuration
```
admin@sonic:~$ show logrotate
Usage: show logrotate [OPTIONS] COMMAND [ARGS]...

Show logrotate configuration

Options:
-?, -h, --help Show this message and exit.
```
```
admin@sonic:~$ show logrotate
file disk-percentage frequency max-number size
------ ----------------- ----------- ------------ ------
syslog 10.2 daily 10 20.0
debug 50.5 weekly 20 10.0

```
23 changes: 23 additions & 0 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,29 @@ def received(db, namespace):
ctx.fail("ASIC/SDK health event is not supported on the platform")


#
# 'logrorare' command group ("show logrotate ...")
#
@cli.group('logrotate', invoke_without_command=True)
@clicommon.pass_db
def logrotate(db):
"""Show logrotate configuration"""

table = []

logging_table = db.cfgdb.get_table('LOGGING')
for key, value in logging_table.items():
disk_percentage = value.get('disk_percentage', '')
frequency = value.get('frequency', '')
max_number = value.get('max_number', '')
size = value.get('size', '')

table.append((key, disk_percentage, frequency, max_number, size))

hdrs = ['file', 'disk-percentage', 'frequency', 'max-number', 'size (MiB)']
click.echo(tabulate(table, headers=hdrs, tablefmt='simple', missingval=''))


# Load plugins and register them
helper = util_base.UtilHelper()
helper.load_and_register_plugins(plugins, cli)
Expand Down
52 changes: 52 additions & 0 deletions tests/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3729,3 +3729,55 @@ def teardown_class(cls):
from .mock_tables import mock_single_asic
importlib.reload(mock_single_asic)
dbconnector.load_database_config()


class TestConfigLogrotate(object):
@classmethod
def setup_class(cls):
print('SETUP')
import config.main
importlib.reload(config.main)

@patch('utilities_common.cli.run_command',
mock.MagicMock(side_effect=mock_run_command_side_effect))
def test_logrotate_disk_percentage(self):
runner = CliRunner()
obj = {'db': Db().cfgdb}

result = runner.invoke(config.config.commands['logrotate'],
['debug', 'disk-percentage', '24.25'], obj=obj)
assert result.exit_code == 0

@patch('utilities_common.cli.run_command',
mock.MagicMock(side_effect=mock_run_command_side_effect))
def test_logrotate_frequency(self):
runner = CliRunner()
obj = {'db': Db().cfgdb}

result = runner.invoke(config.config.commands['logrotate'],
['debug', 'frequency', 'daily'], obj=obj)
assert result.exit_code == 0

@patch('utilities_common.cli.run_command',
mock.MagicMock(side_effect=mock_run_command_side_effect))
def test_logrotate_max_number(self):
runner = CliRunner()
obj = {'db': Db().cfgdb}

result = runner.invoke(config.config.commands['logrotate'],
['syslog', 'max-number', '2024'], obj=obj)
assert result.exit_code == 0

@patch('utilities_common.cli.run_command',
mock.MagicMock(side_effect=mock_run_command_side_effect))
def test_logrotate_size(self):
runner = CliRunner()
obj = {'db': Db().cfgdb}

result = runner.invoke(config.config.commands['logrotate'],
['syslog', 'size', '30.0'], obj=obj)
assert result.exit_code == 0

@classmethod
def teardown_class(cls):
print('TEARDOWN')
6 changes: 6 additions & 0 deletions tests/show_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,12 @@ def test_show_ztp(self, mock_run_command):
assert result.exit_code == 0
mock_run_command.assert_called_with(['ztp', 'status', '--verbose'], display_cmd=True)

@patch('show.main.run_command')
def test_show_logrotate(self, mock_run_command):
runner = CliRunner()
result = runner.invoke(show.cli.commands['logrotate'])
assert result.exit_code == 0

def teardown(self):
print('TEAR DOWN')

Expand Down
Loading