Skip to content

Commit

Permalink
[dualtor_neighbor_check] Fix the script not exists issue (sonic-net#3244
Browse files Browse the repository at this point in the history
)

What I did
Fix sonic-net/sonic-buildimage#17200

Microsoft ADO (number only): 27317600
Upon advanced-reboot, the Lua script is flushed, so the EVALSHA command
might suffer from the script not-existed issue. Let's check if the
script exists before calling EVALSHA.

Signed-off-by: Longxiang Lyu [email protected]

How I did it
As the above.

How to verify it
UT and verify on dualtor testbed.

Previous command output (if the output of a command-line utility has changed)
New command output (if the output of a command-line utility has changed)
  • Loading branch information
lolyu authored and arfeigin committed Apr 2, 2024
1 parent 6471d9b commit 05e2b64
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 13 deletions.
13 changes: 11 additions & 2 deletions scripts/dualtor_neighbor_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,21 @@ def read_tables_from_db(appl_db):
"""Reads required tables from db."""
# NOTE: let's cache the db read script sha1 in APPL_DB under
# key "_DUALTOR_NEIGHBOR_CHECK_SCRIPT_SHA1"
db_read_script_sha1 = appl_db.get(DB_READ_SCRIPT_CONFIG_DB_KEY)
if not db_read_script_sha1:
def _load_script():
redis_load_cmd = "SCRIPT LOAD \"%s\"" % DB_READ_SCRIPT
db_read_script_sha1 = redis_cli(redis_load_cmd).strip()
WRITE_LOG_INFO("loaded script sha1: %s", db_read_script_sha1)
appl_db.set(DB_READ_SCRIPT_CONFIG_DB_KEY, db_read_script_sha1)
return db_read_script_sha1

def _is_script_existed(script_sha1):
redis_script_exists_cmd = "SCRIPT EXISTS %s" % script_sha1
cmd_output = redis_cli(redis_script_exists_cmd).strip()
return "1" in cmd_output

db_read_script_sha1 = appl_db.get(DB_READ_SCRIPT_CONFIG_DB_KEY)
if ((not db_read_script_sha1) or (not _is_script_existed(db_read_script_sha1))):
db_read_script_sha1 = _load_script()

redis_run_cmd = "EVALSHA %s 0" % db_read_script_sha1
result = redis_cli(redis_run_cmd).strip()
Expand Down
72 changes: 61 additions & 11 deletions tests/dualtor_neighbor_check_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,31 +235,81 @@ def test_read_from_db(self, mock_log_functions):
assert asic_route_table == result[4]
assert asic_neigh_table == result[5]

def test_read_from_db_with_lua_cache(self, mock_log_functions):
def test_read_from_db_script_not_existed(self, mock_log_functions):
with patch("dualtor_neighbor_check.run_command") as mock_run_command:
neighbors = {"192.168.0.2": "ee:86:d8:46:7d:01"}
mux_states = {"Ethernet4": "active"}
hw_mux_states = {"Ethernet4": "active"}
asic_fdb = {"ee:86:d8:46:7d:01": "oid:0x3a00000000064b"}
asic_route_table = []
asic_neigh_table = ["{\"ip\":\"192.168.0.23\",\"rif\":\"oid:0x6000000000671\",\"switch_id\":\"oid:0x21000000000000\"}"]
mock_run_command.return_value = json.dumps(
{
"neighbors": neighbors,
"mux_states": mux_states,
"hw_mux_states": hw_mux_states,
"asic_fdb": asic_fdb,
"asic_route_table": asic_route_table,
"asic_neigh_table": asic_neigh_table
}
mock_run_command.side_effect = [
"(integer) 0",
"c53fd5eaad68be1e66a2fe80cd20a9cb18c91259",
json.dumps(
{
"neighbors": neighbors,
"mux_states": mux_states,
"hw_mux_states": hw_mux_states,
"asic_fdb": asic_fdb,
"asic_route_table": asic_route_table,
"asic_neigh_table": asic_neigh_table
}
)
]
mock_appl_db = MagicMock()
mock_appl_db.get = MagicMock(return_value="c53fd5eaad68be1e66a2fe80cd20a9cb18c91259")

result = dualtor_neighbor_check.read_tables_from_db(mock_appl_db)

mock_appl_db.get.assert_called_once_with("_DUALTOR_NEIGHBOR_CHECK_SCRIPT_SHA1")
mock_run_command.assert_has_calls(
[
call("sudo redis-cli SCRIPT EXISTS c53fd5eaad68be1e66a2fe80cd20a9cb18c91259"),
call("sudo redis-cli SCRIPT LOAD \"%s\"" % dualtor_neighbor_check.DB_READ_SCRIPT),
call("sudo redis-cli EVALSHA c53fd5eaad68be1e66a2fe80cd20a9cb18c91259 0")
]
)
assert neighbors == result[0]
assert mux_states == result[1]
assert hw_mux_states == result[2]
assert {k: v.lstrip("oid:0x") for k, v in asic_fdb.items()} == result[3]
assert asic_route_table == result[4]
assert asic_neigh_table == result[5]

def test_read_from_db_with_lua_cache(self, mock_log_functions):
with patch("dualtor_neighbor_check.run_command") as mock_run_command:
neighbors = {"192.168.0.2": "ee:86:d8:46:7d:01"}
mux_states = {"Ethernet4": "active"}
hw_mux_states = {"Ethernet4": "active"}
asic_fdb = {"ee:86:d8:46:7d:01": "oid:0x3a00000000064b"}
asic_route_table = []
asic_neigh_table = ["{\"ip\":\"192.168.0.23\",\"rif\":\"oid:0x6000000000671\",\"switch_id\":\"oid:0x21000000000000\"}"]
mock_run_command.side_effect = [
"(integer) 1",
json.dumps(
{
"neighbors": neighbors,
"mux_states": mux_states,
"hw_mux_states": hw_mux_states,
"asic_fdb": asic_fdb,
"asic_route_table": asic_route_table,
"asic_neigh_table": asic_neigh_table
}
)
]
mock_appl_db = MagicMock()
mock_appl_db.get = MagicMock(return_value="c53fd5eaad68be1e66a2fe80cd20a9cb18c91259")

result = dualtor_neighbor_check.read_tables_from_db(mock_appl_db)

mock_appl_db.get.assert_called_once_with("_DUALTOR_NEIGHBOR_CHECK_SCRIPT_SHA1")
mock_run_command.assert_called_once_with("sudo redis-cli EVALSHA c53fd5eaad68be1e66a2fe80cd20a9cb18c91259 0")
mock_run_command.assert_has_calls(
[
call("sudo redis-cli SCRIPT EXISTS c53fd5eaad68be1e66a2fe80cd20a9cb18c91259"),
call("sudo redis-cli EVALSHA c53fd5eaad68be1e66a2fe80cd20a9cb18c91259 0")
]
)
assert neighbors == result[0]
assert mux_states == result[1]
assert hw_mux_states == result[2]
Expand Down

0 comments on commit 05e2b64

Please sign in to comment.