forked from sonic-net/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reliable TSA implementation (sonic-net#18928)
* Reliable TSA implementation --------- Signed-off-by: fountzou <[email protected]>
- Loading branch information
Showing
11 changed files
with
328 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from .manager import Manager | ||
from .managers_device_global import DeviceGlobalCfgMgr | ||
from .log import log_err, log_debug, log_notice | ||
import re | ||
from swsscommon import swsscommon | ||
|
||
class ChassisAppDbMgr(Manager): | ||
"""This class responds to change in tsa_enabled state of the supervisor""" | ||
|
||
def __init__(self, common_objs, db, table): | ||
""" | ||
Initialize the object | ||
:param common_objs: common object dictionary | ||
:param db: name of the db | ||
:param table: name of the table in the db | ||
""" | ||
self.lc_tsa = "" | ||
self.directory = common_objs['directory'] | ||
self.dev_cfg_mgr = DeviceGlobalCfgMgr(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_DEVICE_GLOBAL_TABLE_NAME) | ||
self.directory.subscribe([("CONFIG_DB", swsscommon.CFG_BGP_DEVICE_GLOBAL_TABLE_NAME, "tsa_enabled"),], self.on_lc_tsa_status_change) | ||
super(ChassisAppDbMgr, self).__init__( | ||
common_objs, | ||
[], | ||
db, | ||
table, | ||
) | ||
|
||
def on_lc_tsa_status_change(self): | ||
if self.directory.path_exist("CONFIG_DB", swsscommon.CFG_BGP_DEVICE_GLOBAL_TABLE_NAME, "tsa_enabled"): | ||
self.lc_tsa = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_BGP_DEVICE_GLOBAL_TABLE_NAME)["tsa_enabled"] | ||
log_debug("ChassisAppDbMgr:: LC TSA update handler status %s" % self.lc_tsa) | ||
|
||
def set_handler(self, key, data): | ||
log_debug("ChassisAppDbMgr:: set handler") | ||
|
||
if not data: | ||
log_err("ChassisAppDbMgr:: data is None") | ||
return False | ||
|
||
if "tsa_enabled" in data: | ||
if self.lc_tsa == "false": | ||
self.dev_cfg_mgr.cfg_mgr.commit() | ||
self.dev_cfg_mgr.cfg_mgr.update() | ||
self.dev_cfg_mgr.isolate_unisolate_device(data["tsa_enabled"]) | ||
return True | ||
return False | ||
|
||
def del_handler(self, key): | ||
log_debug("ChassisAppDbMgr:: del handler") | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
from unittest.mock import MagicMock, patch | ||
|
||
import os | ||
from bgpcfgd.directory import Directory | ||
from bgpcfgd.template import TemplateFabric | ||
from . import swsscommon_test | ||
from .util import load_constants | ||
import bgpcfgd.managers_chassis_app_db | ||
import bgpcfgd.managers_device_global | ||
from swsscommon import swsscommon | ||
from copy import deepcopy | ||
|
||
TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') | ||
BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/general/peer-group.conf/') | ||
INTERNAL_BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/internal/peer-group.conf/') | ||
global_constants = { | ||
"bgp": { | ||
"traffic_shift_community" :"12345:12345", | ||
"internal_community_match_tag" : "1001" | ||
} | ||
} | ||
|
||
def constructor(check_internal=False): | ||
cfg_mgr = MagicMock() | ||
def get_text(): | ||
text = [] | ||
for line in cfg_mgr.changes.split('\n'): | ||
if line.lstrip().startswith('!'): | ||
continue | ||
text.append(line) | ||
text += [" "] | ||
return text | ||
def update(): | ||
if check_internal: | ||
cfg_mgr.changes = get_string_from_file("/result_chasiss_packet.conf", INTERNAL_BASE_PATH) | ||
else: | ||
cfg_mgr.changes = get_string_from_file("/result_all.conf") | ||
def push(cfg): | ||
cfg_mgr.changes += cfg + "\n" | ||
def get_config(): | ||
return cfg_mgr.changes | ||
cfg_mgr.get_text = get_text | ||
cfg_mgr.update = update | ||
cfg_mgr.push = push | ||
cfg_mgr.get_config = get_config | ||
|
||
constants = deepcopy(global_constants) | ||
common_objs = { | ||
'directory': Directory(), | ||
'cfg_mgr': cfg_mgr, | ||
'tf': TemplateFabric(TEMPLATE_PATH), | ||
'constants': constants | ||
} | ||
mgr = bgpcfgd.managers_chassis_app_db.ChassisAppDbMgr(common_objs, "CHASSIS_APP_DB", "BGP_DEVICE_GLOBAL") | ||
cfg_mgr.update() | ||
return mgr | ||
|
||
|
||
@patch('bgpcfgd.managers_device_global.log_debug') | ||
def test_isolate_device(mocked_log_info): | ||
m = constructor() | ||
|
||
m.lc_tsa = "false" | ||
res = m.set_handler("STATE", {"tsa_enabled": "true"}) | ||
assert res, "Expect True return value for set_handler" | ||
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") | ||
assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_isolate.conf") | ||
|
||
curr_cfg = m.cfg_mgr.get_config() | ||
m.lc_tsa = "true" | ||
res = m.set_handler("STATE", {"tsa_enabled": "true"}) | ||
assert res, "Expect True return value for set_handler" | ||
assert m.cfg_mgr.get_config() == curr_cfg | ||
|
||
@patch('bgpcfgd.managers_device_global.log_debug') | ||
def test_isolate_device_internal_session(mocked_log_info): | ||
m = constructor(check_internal=True) | ||
|
||
m.lc_tsa = "false" | ||
res = m.set_handler("STATE", {"tsa_enabled": "true"}) | ||
assert res, "Expect True return value for set_handler" | ||
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") | ||
assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_isolate.conf", INTERNAL_BASE_PATH) | ||
|
||
curr_cfg = m.cfg_mgr.get_config() | ||
m.lc_tsa = "true" | ||
res = m.set_handler("STATE", {"tsa_enabled": "true"}) | ||
assert res, "Expect True return value for set_handler" | ||
assert m.cfg_mgr.get_config() == curr_cfg | ||
|
||
|
||
@patch('bgpcfgd.managers_device_global.log_debug') | ||
def test_unisolate_device(mocked_log_info): | ||
m = constructor() | ||
|
||
m.lc_tsa = "false" | ||
res = m.set_handler("STATE", {"tsa_enabled": "false"}) | ||
assert res, "Expect True return value for set_handler" | ||
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") | ||
assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_unisolate.conf") | ||
|
||
curr_cfg = m.cfg_mgr.get_config() | ||
m.lc_tsa = "true" | ||
res = m.set_handler("STATE", {"tsa_enabled": "false"}) | ||
assert res, "Expect True return value for set_handler" | ||
assert m.cfg_mgr.get_config() == curr_cfg | ||
|
||
@patch('bgpcfgd.managers_device_global.log_debug') | ||
def test_unisolate_device_internal_session(mocked_log_info): | ||
m = constructor(check_internal=True) | ||
|
||
m.lc_tsa = "false" | ||
res = m.set_handler("STATE", {"tsa_enabled": "false"}) | ||
assert res, "Expect True return value for set_handler" | ||
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") | ||
assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_unisolate.conf", INTERNAL_BASE_PATH) | ||
|
||
curr_cfg = m.cfg_mgr.get_config() | ||
m.lc_tsa = "true" | ||
res = m.set_handler("STATE", {"tsa_enabled": "false"}) | ||
assert res, "Expect True return value for set_handler" | ||
assert m.cfg_mgr.get_config() == curr_cfg | ||
|
||
|
||
def get_string_from_file(filename, base_path=BASE_PATH): | ||
fp = open(base_path + filename, "r") | ||
cfg = fp.read() | ||
fp.close() | ||
|
||
return cfg | ||
|
||
@patch('bgpcfgd.managers_chassis_app_db.log_err') | ||
def test_set_handler_failure_case(mocked_log_info): | ||
m = constructor() | ||
res = m.set_handler("STATE", {}) | ||
assert res == False, "Expect False return value for invalid data passed to set_handler" | ||
mocked_log_info.assert_called_with("ChassisAppDbMgr:: data is None") | ||
|
||
def test_del_handler(): | ||
m = constructor() | ||
res = m.del_handler("STATE") | ||
assert res, "Expect True return value for del_handler" |
Oops, something went wrong.