Coverage for birdplan/plugins/cmdline/bgp/peer/summary.py: 51%
68 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
1#
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4# Copyright (c) 2019-2024, AllWorldIT
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
19"""BirdPlan commandline options for BGP peer summary."""
21import argparse
22import io
23from typing import Any, Dict
25from ..... import BirdPlanBGPPeerSummary
26from .....cmdline import BirdPlanCommandLine, BirdPlanCommandlineResult
27from .....console.colors import colored
28from .....exceptions import BirdPlanErrorUsage
29from ...cmdline_plugin import BirdPlanCmdlinePluginBase
31__all__ = ["BirdPlanCmdlineBGPPeerShow"]
34class BirdPlanCmdlineBGPPeerShowResult(BirdPlanCommandlineResult):
35 """BirdPlan BGP peer show result."""
37 def as_text(self) -> str:
38 """
39 Return data in text format.
41 Returns
42 -------
43 str
44 Return data in text format.
46 """
48 ob = io.StringIO()
50 # Write out header
51 ob.write(f"+{'='*130}+\n")
52 ob.write(f"| {'BGP Peer Summary'.center(128)} |\n")
53 ob.write(f"+{'-'*34}+{'-'*10}+{'-'*10}+{'-'*21}+{'-'*51}+\n")
54 ob.write(
55 f"| {'Peer Name'.center(32)} "
56 f"| {'Proto'.center(8)} "
57 f"| {'Status'.center(8)} "
58 f"| {'Since'.center(19)} "
59 f"| {'Info'.center(49)} |\n"
60 )
61 ob.write(f"+{'-'*34}+{'-'*10}+{'-'*10}+{'-'*21}+{'-'*51}+\n")
63 # Loop with each protocol
64 for peer_name, peer in self.data.items():
65 # Loop with each family
66 for ipv, protocol in peer["protocols"].items():
67 protocol_status = protocol["status"]
69 # Start with plain strings with no color
70 state: str = protocol_status["state"]
71 info: str = protocol_status["info"]
72 since: str = protocol_status["since"]
74 # NK - Update in peer_arg show too
75 # Check how we're going to color entries based on their state and info
76 state_out = f"{state[:8]}".center(8)
77 info_out = f"{info[:49]}".center(49)
78 if protocol_status["state"] == "down":
79 state_out = colored(f"{state[:8]}".center(8), "red")
80 if "info_extra" in protocol_status:
81 info += " - " + protocol_status["info_extra"]
82 info_out = colored(f"{info[:49]}".center(49), "red")
83 elif protocol_status["state"] == "up": # noqa: SIM102
84 if protocol_status["info"] == "established":
85 state_out = colored(f"{state[:8]}".center(8), "green")
86 info_out = colored(f"{info[:49]}".center(49), "green")
88 # Center some columns
89 ipv_out = f"{ipv[:8]}".center(8)
91 # Write out info line
92 ob.write(f"| {peer_name[:32]:<32} | {ipv_out} | {state_out} | {since[:19]:<19} | {info_out} |\n")
94 # Write out footer
95 ob.write(f"+{'='*130}+\n")
97 return ob.getvalue()
100class BirdPlanCmdlineBGPPeerShow(BirdPlanCmdlinePluginBase):
101 """BirdPlan "bgp peer summary" command."""
103 def __init__(self) -> None:
104 """Initialize object."""
106 super().__init__()
108 # Plugin setup
109 self.plugin_description = "birdplan bgp peer summary"
110 self.plugin_order = 20
112 def register_parsers(self, args: Dict[str, Any]) -> None:
113 """
114 Register commandline parsers.
116 Parameters
117 ----------
118 args : Dict[str, Any]
119 Method argument(s).
121 """
123 plugins = args["plugins"]
125 parent_subparsers = plugins.call_plugin("birdplan.plugins.cmdline.bgp.peer", "get_subparsers", {})
127 # CMD: bgp peer summary
128 subparser = parent_subparsers.add_parser("summary", help="BGP peer summary commands")
129 subparser.add_argument(
130 "--action",
131 action="store_const",
132 const="bgp_peer_summary",
133 default="bgp_peer_summary",
134 help=argparse.SUPPRESS,
135 )
137 subparser.add_argument(
138 "--only",
139 nargs=1,
140 default=None,
141 metavar="ONLY",
142 help="Limit output to: AS<NUMBER>",
143 )
145 # Set our internal subparser property
146 self._subparser = subparser
147 self._subparsers = None
149 def cmd_bgp_peer_summary(self, args: Any) -> Any: # pylint: disable=unused-argument
150 """
151 Commandline handler for "bgp peer summary" action.
153 Parameters
154 ----------
155 args : Dict[str, Any]
156 Method argument(s).
158 """
160 if not self._subparser: # pragma: no cover
161 raise RuntimeError()
163 cmdline: BirdPlanCommandLine = args["cmdline"]
165 # Validate extra options
166 arg_only = None
167 if cmdline.args.only:
168 if cmdline.args.only[0][0:2] != "AS":
169 raise BirdPlanErrorUsage("Invalid value for --only, must be AS<NUMBER>")
170 if int(cmdline.args.only[0]) < 1:
171 raise BirdPlanErrorUsage("Invalid value for --only, must be AS<NUMBER>")
172 # Save the arg for later
173 arg_only = cmdline.args.only[0]
175 # Grab Bird control socket
176 bird_socket = cmdline.args.bird_socket[0]
178 # Suppress info output
179 cmdline.birdplan.birdconf.birdconfig_globals.suppress_info = True
181 # Load BirdPlan configuration using the cache
182 cmdline.birdplan_load_config(ignore_irr_changes=True, ignore_peeringdb_changes=True, use_cached=True)
184 # Grab peer list
185 peer_list: BirdPlanBGPPeerSummary = cmdline.birdplan.state_bgp_peer_summary(bird_socket=bird_socket)
187 # Check if we're filtering on a specific AS
188 if arg_only and arg_only[0:2] == "AS":
189 peer_list = {k: v for k, v in peer_list.items() if v["asn"] == int(arg_only[2:])}
191 return BirdPlanCmdlineBGPPeerShowResult(peer_list)