Skip to content

Commit 75bb60f

Browse files
committed
YANG validation for ConfigDB Updates: MIRROR_SESSION use case (sonic-net#2430)
1 parent cf3f0ce commit 75bb60f

File tree

3 files changed

+129
-20
lines changed

3 files changed

+129
-20
lines changed

config/main.py

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,25 +2355,35 @@ def add_erspan(session_name, src_ip, dst_ip, dscp, ttl, gre_type, queue, policer
23552355
session_info['gre_type'] = gre_type
23562356

23572357
session_info = gather_session_info(session_info, policer, queue, src_port, direction)
2358+
ctx = click.get_current_context()
23582359

23592360
"""
23602361
For multi-npu platforms we need to program all front asic namespaces
23612362
"""
23622363
namespaces = multi_asic.get_all_namespaces()
23632364
if not namespaces['front_ns']:
2364-
config_db = ConfigDBConnector()
2365+
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
23652366
config_db.connect()
2366-
if validate_mirror_session_config(config_db, session_name, None, src_port, direction) is False:
2367-
return
2368-
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
2367+
if ADHOC_VALIDATION:
2368+
if validate_mirror_session_config(config_db, session_name, None, src_port, direction) is False:
2369+
return
2370+
try:
2371+
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
2372+
except ValueError as e:
2373+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
2374+
23692375
else:
23702376
per_npu_configdb = {}
23712377
for front_asic_namespaces in namespaces['front_ns']:
2372-
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
2378+
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
23732379
per_npu_configdb[front_asic_namespaces].connect()
2374-
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, None, src_port, direction) is False:
2375-
return
2376-
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
2380+
if ADHOC_VALIDATION:
2381+
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, None, src_port, direction) is False:
2382+
return
2383+
try:
2384+
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
2385+
except ValueError as e:
2386+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
23772387

23782388
@mirror_session.group(cls=clicommon.AbbreviationGroup, name='span')
23792389
@click.pass_context
@@ -2405,25 +2415,34 @@ def add_span(session_name, dst_port, src_port, direction, queue, policer):
24052415
}
24062416

24072417
session_info = gather_session_info(session_info, policer, queue, src_port, direction)
2418+
ctx = click.get_current_context()
24082419

24092420
"""
24102421
For multi-npu platforms we need to program all front asic namespaces
24112422
"""
24122423
namespaces = multi_asic.get_all_namespaces()
24132424
if not namespaces['front_ns']:
2414-
config_db = ConfigDBConnector()
2425+
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
24152426
config_db.connect()
2416-
if validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction) is False:
2417-
return
2418-
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
2427+
if ADHOC_VALIDATION:
2428+
if validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction) is False:
2429+
return
2430+
try:
2431+
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
2432+
except ValueError as e:
2433+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
24192434
else:
24202435
per_npu_configdb = {}
24212436
for front_asic_namespaces in namespaces['front_ns']:
2422-
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
2437+
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
24232438
per_npu_configdb[front_asic_namespaces].connect()
2424-
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, dst_port, src_port, direction) is False:
2425-
return
2426-
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
2439+
if ADHOC_VALIDATION:
2440+
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, dst_port, src_port, direction) is False:
2441+
return
2442+
try:
2443+
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
2444+
except ValueError as e:
2445+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
24272446

24282447

24292448
@mirror_session.command()
@@ -2435,16 +2454,23 @@ def remove(session_name):
24352454
For multi-npu platforms we need to program all front asic namespaces
24362455
"""
24372456
namespaces = multi_asic.get_all_namespaces()
2457+
ctx = click.get_current_context()
24382458
if not namespaces['front_ns']:
2439-
config_db = ConfigDBConnector()
2459+
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
24402460
config_db.connect()
2441-
config_db.set_entry("MIRROR_SESSION", session_name, None)
2461+
try:
2462+
config_db.set_entry("MIRROR_SESSION", session_name, None)
2463+
except JsonPatchConflict as e:
2464+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
24422465
else:
24432466
per_npu_configdb = {}
24442467
for front_asic_namespaces in namespaces['front_ns']:
2445-
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
2468+
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
24462469
per_npu_configdb[front_asic_namespaces].connect()
2447-
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, None)
2470+
try:
2471+
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, None)
2472+
except JsonPatchConflict as e:
2473+
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
24482474

24492475
#
24502476
# 'pfcwd' group ('config pfcwd ...')

tests/config_mirror_session_test.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import pytest
22
import config.main as config
3+
import jsonpatch
34
from unittest import mock
45
from click.testing import CliRunner
6+
from mock import patch
7+
from jsonpatch import JsonPatchConflict
8+
from sonic_py_common import multi_asic
59

610
ERR_MSG_IP_FAILURE = "does not appear to be an IPv4 or IPv6 network"
711
ERR_MSG_IP_VERSION_FAILURE = "not a valid IPv4 address"
@@ -172,7 +176,34 @@ def test_mirror_session_erspan_add():
172176
mocked.assert_called_with("test_session", "100.1.1.1", "2.2.2.2", 8, 63, 0, 0, None, None, None)
173177

174178

179+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
180+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))
181+
def test_mirror_session_erspan_add_invalid_yang_validation():
182+
config.ADHOC_VALIDATION = False
183+
runner = CliRunner()
184+
result = runner.invoke(
185+
config.config.commands["mirror_session"].commands["erspan"].commands["add"],
186+
["test_session", "100.1.1.1", "2.2.2.2", "8", "63", "10", "100"])
187+
print(result.output)
188+
assert "Invalid ConfigDB. Error" in result.output
189+
190+
191+
@patch("config.main.ConfigDBConnector", spec=True, connect=mock.Mock())
192+
@patch("config.main.multi_asic.get_all_namespaces", mock.Mock(return_value={'front_ns': 'sample_ns'}))
193+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
194+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))
195+
def test_mirror_session_erspan_add_multi_asic_invalid_yang_validation(mock_db_connector):
196+
config.ADHOC_VALIDATION = False
197+
runner = CliRunner()
198+
result = runner.invoke(
199+
config.config.commands["mirror_session"].commands["erspan"].commands["add"],
200+
["test_session", "100.1.1.1", "2.2.2.2", "8", "63", "10", "100"])
201+
print(result.output)
202+
assert "Invalid ConfigDB. Error" in result.output
203+
204+
175205
def test_mirror_session_span_add():
206+
config.ADHOC_VALIDATION = True
176207
runner = CliRunner()
177208

178209
# Verify invalid queue
@@ -273,3 +304,54 @@ def test_mirror_session_span_add():
273304

274305
mocked.assert_called_with("test_session", "Ethernet0", "Ethernet4", "rx", 0, None)
275306

307+
308+
@patch("config.main.ConfigDBConnector", spec=True, connect=mock.Mock())
309+
@patch("config.main.multi_asic.get_all_namespaces", mock.Mock(return_value={'front_ns': 'sample_ns'}))
310+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
311+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))
312+
def test_mirror_session_span_add_multi_asic_invalid_yang_validation(mock_db_connector):
313+
config.ADHOC_VALIDATION = False
314+
runner = CliRunner()
315+
result = runner.invoke(
316+
config.config.commands["mirror_session"].commands["span"].commands["add"],
317+
["test_session", "Ethernet0", "Ethernet4", "rx", "0"])
318+
print(result.output)
319+
assert "Invalid ConfigDB. Error" in result.output
320+
321+
322+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
323+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))
324+
def test_mirror_session_span_add_invalid_yang_validation():
325+
config.ADHOC_VALIDATION = False
326+
runner = CliRunner()
327+
result = runner.invoke(
328+
config.config.commands["mirror_session"].commands["span"].commands["add"],
329+
["test_session", "Ethernet0", "Ethernet4", "rx", "0"])
330+
print(result.output)
331+
assert "Invalid ConfigDB. Error" in result.output
332+
333+
334+
@patch("config.main.multi_asic.get_all_namespaces", mock.Mock(return_value={'front_ns': 'sample_ns'}))
335+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
336+
@patch("config.main.ConfigDBConnector", spec=True, connect=mock.Mock())
337+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=JsonPatchConflict))
338+
def test_mirror_session_remove_multi_asic_invalid_yang_validation(mock_db_connector):
339+
config.ADHOC_VALIDATION = False
340+
runner = CliRunner()
341+
result = runner.invoke(
342+
config.config.commands["mirror_session"].commands["remove"],
343+
["mrr_sample"])
344+
print(result.output)
345+
assert "Invalid ConfigDB. Error" in result.output
346+
347+
348+
@patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True))
349+
@patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=JsonPatchConflict))
350+
def test_mirror_session_remove_invalid_yang_validation():
351+
config.ADHOC_VALIDATION = False
352+
runner = CliRunner()
353+
result = runner.invoke(
354+
config.config.commands["mirror_session"].commands["remove"],
355+
["mrr_sample"])
356+
print(result.output)
357+
assert "Invalid ConfigDB. Error" in result.output

tests/config_snmp_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def setup_class(cls):
118118

119119
# Add snmp community tests
120120
def test_config_snmp_community_add_new_community_ro(self):
121+
config.ADHOC_VALIDATION = True
121122
db = Db()
122123
runner = CliRunner()
123124
with mock.patch('utilities_common.cli.run_command') as mock_run_command:

0 commit comments

Comments
 (0)