From 908ac61206daaa23d0b8ad72eab9340792c68ac6 Mon Sep 17 00:00:00 2001 From: Michael Liu Date: Thu, 11 Jan 2024 12:09:00 -0800 Subject: [PATCH] Add partial adj detection to breeze Summary: We can now ask a node to display all partial adj of an area, in its perspective Reviewed By: xiangxu1121 Differential Revision: D52643484 fbshipit-source-id: 11a1895164fdac1b6836fe38c0fbbb579ce9a09e --- openr/py/openr/cli/clis/decision.py | 11 ++++++++ openr/py/openr/cli/commands/decision.py | 35 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/openr/py/openr/cli/clis/decision.py b/openr/py/openr/cli/clis/decision.py index 0b266a7637e..f22724e4c20 100644 --- a/openr/py/openr/cli/clis/decision.py +++ b/openr/py/openr/cli/clis/decision.py @@ -23,6 +23,7 @@ def __init__(self): self.decision.add_command(DecisionRibPolicyCli().show, name="rib-policy") self.decision.add_command(ReceivedRoutesCli().show) self.decision.add_command(DecisionValidateCli().validate) + self.decision.add_command(DecisionPartialAdjCli().show, name="partial-adj") @click.group(cls=deduceCommandGroup) @click.pass_context @@ -83,6 +84,16 @@ def routes(cli_opts, nodes, prefixes, labels, hostnames, json): # noqa: B902 ) +class DecisionPartialAdjCli: + @click.command() + @click.option("--area", "-a", help="Show partial adj for the given area") + @click.pass_obj + def show(cli_opts, area): # noqa: B902 + """dump the partial adjacencies of an area""" + + decision.DecisionShowPartialAdjCmd(cli_opts).run(area) + + class DecisionAdjCli: @click.command() @click.option( diff --git a/openr/py/openr/cli/commands/decision.py b/openr/py/openr/cli/commands/decision.py index 13c44b4c210..82d94b69de2 100644 --- a/openr/py/openr/cli/commands/decision.py +++ b/openr/py/openr/cli/commands/decision.py @@ -56,6 +56,41 @@ async def _run( ) +class DecisionShowPartialAdjCmd(OpenrCtrlCmd): + # pyre-fixme[14]: `_run` overrides method defined in `OpenrCtrlCmd` inconsistently. + async def _run( + self, + client: OpenrCtrlCppClient.Async, + area: str, + *args, + **kwargs, + ) -> None: + adj_dbs = await client.getDecisionAdjacenciesFiltered( + ctrl_types.AdjacenciesFilter(selectAreas={area}) + ) + # convert list from server to a two level map: {area: {node: adjDb}} + adjs_map_all_areas = utils.adj_dbs_to_area_dict( + adj_dbs, nodes={"all"}, bidir=False + ) + + print("\n== Area:", area, "==\n") + adj_set = set() + for _, adj_dbs in adjs_map_all_areas.items(): + for node_name, adj_db in adj_dbs.items(): + for adj in adj_db["adjacencies"]: + adj_set.add((node_name, adj["otherNodeName"])) + print("Total adj (uni-directional):", len(adj_set)) + + missing = [] + for node, adj in adj_set: + r = (adj, node) + if r not in adj_set: + missing.append(r) + print("Total partial adj:", len(missing)) + for missing_adj in sorted(missing): + print(f"{missing_adj[0]} -X-> {missing_adj[1]}") + + class DecisionAdjCmd(OpenrCtrlCmd): # pyre-fixme[14]: `_run` overrides method defined in `OpenrCtrlCmd` inconsistently. async def _run(