Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into 202305-revert-bgp-suppress-fib-pending

Signed-off-by: Stepan Blyschak <[email protected]>
  • Loading branch information
stepanblyschak committed Dec 26, 2023
2 parents b5326ab + fc4b333 commit 0ff2a0b
Show file tree
Hide file tree
Showing 13 changed files with 449 additions and 13 deletions.
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 @@ -9855,6 +9855,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
77 changes: 75 additions & 2 deletions generic_config_updater/field_operation_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import subprocess
from sonic_py_common import device_info
from .gu_common import GenericConfigUpdaterError

from swsscommon import swsscommon
from utilities_common.constants import DEFAULT_SUPPORTED_FECS_LIST

SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
GCU_TABLE_MOD_CONF_FILE = f"{SCRIPT_DIR}/gcu_field_operation_validators.conf.json"
Expand Down Expand Up @@ -75,7 +76,7 @@ def rdma_config_update_validator(patch_element):
path = patch_element["path"]
table = jsonpointer.JsonPointer(path).parts[0]

# Helper function to return relevant cleaned paths, consdiers case where the jsonpatch value is a dict
# Helper function to return relevant cleaned paths, considers case where the jsonpatch value is a dict
# For paths like /PFC_WD/Ethernet112/action, remove Ethernet112 from the path so that we can clearly determine the relevant field (i.e. action, not Ethernet112)
def _get_fields_in_patch():
cleaned_fields = []
Expand Down Expand Up @@ -130,3 +131,75 @@ def _get_fields_in_patch():
return False

return True


def read_statedb_entry(table, key, field):
state_db = swsscommon.DBConnector("STATE_DB", 0)
tbl = swsscommon.Table(state_db, table)
return tbl.hget(key, field)[1]


def port_config_update_validator(patch_element):

def _validate_field(field, port, value):
if field == "fec":
supported_fecs_str = read_statedb_entry("PORT_TABLE", port, "supported_fecs")
if supported_fecs_str:
if supported_fecs_str != 'N/A':
supported_fecs_list = [element.strip() for element in supported_fecs_str.split(',')]
else:
supported_fecs_list = []
else:
supported_fecs_list = DEFAULT_SUPPORTED_FECS_LIST
if value.strip() not in supported_fecs_list:
return False
return True
if field == "speed":
supported_speeds_str = read_statedb_entry("PORT_TABLE", port, "supported_speeds") or ''
try:
supported_speeds = [int(s) for s in supported_speeds_str.split(',') if s]
if supported_speeds and int(value) not in supported_speeds:
return False
except ValueError:
return False
return True
return False

def _parse_port_from_path(path):
match = re.search(r"Ethernet\d+", path)
if match:
port = match.group(0)
return port
return None

if patch_element["op"] == "remove":
return True

# for PORT speed and fec configs, need to ensure value is allowed based on StateDB
patch_element_str = json.dumps(patch_element)
path = patch_element["path"]
value = patch_element.get("value")
fields = ['fec', 'speed']
for field in fields:
if field in patch_element_str:
if path.endswith(field):
port = _parse_port_from_path(path)
if not _validate_field(field, port, value):
return False
elif isinstance(value, dict):
if field in value.keys():
port = _parse_port_from_path(path)
value = value[field]
if not _validate_field(field, port, value):
return False
else:
for port_name, port_info in value.items():
if isinstance(port_info, dict):
port = port_name
if field in port_info.keys():
value = port_info[field]
if not _validate_field(field, port, value):
return False
else:
continue
return True
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@
}
}
}
},
"PORT": {
"field_operation_validators": [ "generic_config_updater.field_operation_validators.port_config_update_validator" ]
}
}
}
23 changes: 20 additions & 3 deletions scripts/db_migrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@
class DBMigrator():
def __init__(self, namespace, socket=None):
"""
Version string format:
Version string format (202305 and above):
version_<branch>_<build>
branch: master, 202311, 202305, etc.
build: sequentially increase with leading 0 to make it 2 digits.
because the minor number has been removed to make it different
from the old format, adding a leading 0 to make sure that we
have double digit version number spaces.
Version string format (before 202305):
version_<major>_<minor>_<build>
major: starting from 1, sequentially incrementing in master
branch.
Expand All @@ -47,7 +54,7 @@ def __init__(self, namespace, socket=None):
none-zero values.
build: sequentially increase within a minor version domain.
"""
self.CURRENT_VERSION = 'version_4_0_3'
self.CURRENT_VERSION = 'version_202305_01'

self.TABLE_NAME = 'VERSIONS'
self.TABLE_KEY = 'DATABASE'
Expand Down Expand Up @@ -1008,9 +1015,19 @@ def version_4_0_2(self):
def version_4_0_3(self):
"""
Version 4_0_3.
This is the latest version for master branch
This is the latest version for 202211 branch
"""
log.log_info('Handling version_4_0_3')

self.set_version('version_202305_01')
return 'version_202305_01'

def version_202305_01(self):
"""
Version 202305_01.
This is current last erversion for 202305 branch
"""
log.log_info('Handling version_202305_01')
return None

def get_version(self):
Expand Down
4 changes: 3 additions & 1 deletion scripts/portconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import sys
import decimal
import argparse

from utilities_common.constants import DEFAULT_SUPPORTED_FECS_LIST

# mock the redis for unit test purposes #
try:
if os.environ["UTILITIES_UNIT_TESTING"] == "1" or os.environ["UTILITIES_UNIT_TESTING"] == "2":
Expand Down Expand Up @@ -276,7 +278,7 @@ class portconfig(object):
else:
supported_fecs_list = []
else:
supported_fecs_list = ["rs", "fc", "none"]
supported_fecs_list = DEFAULT_SUPPORTED_FECS_LIST

return supported_fecs_list

Expand Down
6 changes: 4 additions & 2 deletions scripts/route_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,12 @@ def set_level(lvl, log_to_syslog):
report_level = syslog.LOG_DEBUG


def print_message(lvl, *args):
def print_message(lvl, *args, write_to_stdout=True):
"""
print and log the message for given level.
:param lvl: Log level for this message as ERR/INFO/DEBUG
:param args: message as list of strings or convertible to string
:param write_to_stdout: print the message to stdout if set to true
:return None
"""
msg = ""
Expand All @@ -125,7 +126,8 @@ def print_message(lvl, *args):
break
msg += str(arg)[0:rem_len]

print(msg)
if write_to_stdout:
print(msg)
if write_to_syslog:
syslog.syslog(lvl, msg)

Expand Down
Loading

0 comments on commit 0ff2a0b

Please sign in to comment.