-
Notifications
You must be signed in to change notification settings - Fork 685
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
[GCU] Add PFC_WD RDMA validator #2619
Changes from 3 commits
fc7c841
8240d3a
e08a8fe
fdb45b3
b73ff9a
10dd1f5
77bb424
2762e49
f98fc9b
3df33e2
36761e5
633a8fe
987eaa7
735630c
0c6c24e
46c4507
c8f9249
9c15a08
80bf53f
30bd7b2
8d17240
4e29fe7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,7 +48,22 @@ | |
}, | ||
"NTP_SERVER": { | ||
"services_to_validate": [ "ntp-service" ] | ||
} | ||
}, | ||
"PFC_WD": { | ||
"table_modification_validators": [ "generic_config_updater.validators.is_mellanox_device_validator" ] | ||
}, | ||
"BUFFER_POOL": { | ||
"table_modification_validators": [ "generic_config_updater.validators.is_mellanox_device_validator" ] | ||
}, | ||
"WRED_PROFILE": { | ||
"table_modification_validators": [ "generic_config_updater.validators.is_mellanox_device_validator" ] | ||
}, | ||
"QUEUE": { | ||
"table_modification_validators": [ "generic_config_updater.validators.is_mellanox_device_validator" ] | ||
}, | ||
"BUFFER_PROFILE": { | ||
"table_modification_validators": [ "generic_config_updater.validators.is_mellanox_device_validator" ] | ||
} | ||
}, | ||
"services": { | ||
"system_health": { | ||
|
@@ -58,19 +73,19 @@ | |
"validate_commands": [ ] | ||
}, | ||
"rsyslog": { | ||
"validate_commands": [ "generic_config_updater.services_validator.rsyslog_validator" ] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created a new conf file specific to validators that need to be run before the change is applied to ConfigDB There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you keep original name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the new validator If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can place new validator in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new validator is not a MoveValidator, which validates every intermediary move. The preexisting MoveValidators come in during patch sorting. For MoveValidators, if validation fails, the PatchSorter algorithm will continue searching for a new valid move. For this use case, we don't need to start patch sorting at all. Please see a comment I made on a previous PR #2545 describing why we are adding this new infra for one-shot validation at the start (as opposed to MoveValidators for every intermediary move). Quote from linked PR: We don't want to validate each intermediate move to get to the final state, as is done by MoveValidators- we just need to validate the initial request. MoveValidators continue searching for a different move that is 'valid' if it finds one invalid - possibly by deleting the parent and then readding other children. This is not the behavior we desire. We only need a check of the initial request (reflected in Json diff), so we add this extra one-shot validation at the start. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you keep original name services_validator? there is nothing wrong with old code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I changed it back to services_validator. I initially changed it away because I added a non-service validator to this file, but this new non-service validator is now in a new file |
||
"validate_commands": [ "generic_config_updater.validators.rsyslog_validator" ] | ||
}, | ||
"dhcp-relay": { | ||
"validate_commands": [ "generic_config_updater.services_validator.dhcp_validator" ] | ||
"validate_commands": [ "generic_config_updater.validators.dhcp_validator" ] | ||
}, | ||
"vlan-service": { | ||
"validate_commands": [ "generic_config_updater.services_validator.vlan_validator" ] | ||
"validate_commands": [ "generic_config_updater.validators.vlan_validator" ] | ||
}, | ||
"caclmgrd-service": { | ||
"validate_commands": [ "generic_config_updater.services_validator.caclmgrd_validator" ] | ||
"validate_commands": [ "generic_config_updater.validators.caclmgrd_validator" ] | ||
}, | ||
"ntp-service": { | ||
"validate_commands": [ "generic_config_updater.services_validator.ntp_validator" ] | ||
"validate_commands": [ "generic_config_updater.validators.ntp_validator" ] | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,21 @@ | ||
import json | ||
import jsonpatch | ||
import importlib | ||
from jsonpointer import JsonPointer | ||
import sonic_yang | ||
import sonic_yang_ext | ||
import subprocess | ||
import yang as ly | ||
import copy | ||
import re | ||
import os | ||
from sonic_py_common import logger | ||
from enum import Enum | ||
|
||
YANG_DIR = "/usr/local/yang-models" | ||
SYSLOG_IDENTIFIER = "GenericConfigUpdater" | ||
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) | ||
UPDATER_CONF_FILE = f"{SCRIPT_DIR}/generic_config_updater.conf.json" | ||
|
||
class GenericConfigUpdaterError(Exception): | ||
pass | ||
|
@@ -155,6 +159,32 @@ def validate_field_operation(self, old_config, target_config): | |
if any(op['op'] == operation and field == op['path'] for op in patch): | ||
raise IllegalPatchOperationError("Given patch operation is invalid. Operation: {} is illegal on field: {}".format(operation, field)) | ||
|
||
def _invoke_validating_function(cmd): | ||
# cmd is in the format as <package/module name>.<method name> | ||
method_name = cmd.split(".")[-1] | ||
module_name = ".".join(cmd.split(".")[0:-1]) | ||
module = importlib.import_module(module_name, package=None) | ||
method_to_call = getattr(module, method_name) | ||
return method_to_call() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I added code to ensure the module_name is |
||
|
||
if os.path.exists(UPDATER_CONF_FILE): | ||
with open(UPDATER_CONF_FILE, "r") as s: | ||
updater_conf = json.load(s) | ||
else: | ||
raise GenericConfigUpdaterError("GCU Config file not found") | ||
|
||
for element in patch: | ||
path = element["path"] | ||
table = re.search(r'\/([^\/]+)(\/|$)', path).group(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does it match? Could you add an commented example? #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This matches the table name "PFC_WD" and removes any forward slashes at the beginning or end. I added a comment to clarify as well |
||
validating_functions = set() | ||
tables = updater_conf["tables"] | ||
validating_functions.update(tables.get(table, {}).get("table_modification_validators", [])) | ||
|
||
for function in validating_functions: | ||
if not _invoke_validating_function(function): | ||
raise IllegalPatchOperationError("Modification of {} table is illegal- validating function {} returned False".format(table, function)) | ||
|
||
|
||
def validate_lanes(self, config_db): | ||
if "PORT" not in config_db: | ||
return True, None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offline discussed, this is not flexible to express all the rules: ASIC vendor, ASIC generation, and sonic branches. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, the design only allowed for "AND" of all validators.
To address this comment, I added a new section to allow for "OR" check of validators.
Extending the "OR" section to be a list of lists would allow for (X AND Y AND Z) OR (S AND T) checks as well for even greater flexibility.