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

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/>. 

18 

19"""BirdPlan commandline options for BGP peer summary.""" 

20 

21import argparse 

22import io 

23from typing import Any, Dict 

24 

25from ..... import BirdPlanBGPPeerSummary 

26from .....cmdline import BirdPlanCommandLine, BirdPlanCommandlineResult 

27from .....console.colors import colored 

28from .....exceptions import BirdPlanErrorUsage 

29from ...cmdline_plugin import BirdPlanCmdlinePluginBase 

30 

31__all__ = ["BirdPlanCmdlineBGPPeerShow"] 

32 

33 

34class BirdPlanCmdlineBGPPeerShowResult(BirdPlanCommandlineResult): 

35 """BirdPlan BGP peer show result.""" 

36 

37 def as_text(self) -> str: 

38 """ 

39 Return data in text format. 

40 

41 Returns 

42 ------- 

43 str 

44 Return data in text format. 

45 

46 """ 

47 

48 ob = io.StringIO() 

49 

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") 

62 

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"] 

68 

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"] 

73 

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") 

87 

88 # Center some columns 

89 ipv_out = f"{ipv[:8]}".center(8) 

90 

91 # Write out info line 

92 ob.write(f"| {peer_name[:32]:<32} | {ipv_out} | {state_out} | {since[:19]:<19} | {info_out} |\n") 

93 

94 # Write out footer 

95 ob.write(f"+{'='*130}+\n") 

96 

97 return ob.getvalue() 

98 

99 

100class BirdPlanCmdlineBGPPeerShow(BirdPlanCmdlinePluginBase): 

101 """BirdPlan "bgp peer summary" command.""" 

102 

103 def __init__(self) -> None: 

104 """Initialize object.""" 

105 

106 super().__init__() 

107 

108 # Plugin setup 

109 self.plugin_description = "birdplan bgp peer summary" 

110 self.plugin_order = 20 

111 

112 def register_parsers(self, args: Dict[str, Any]) -> None: 

113 """ 

114 Register commandline parsers. 

115 

116 Parameters 

117 ---------- 

118 args : Dict[str, Any] 

119 Method argument(s). 

120 

121 """ 

122 

123 plugins = args["plugins"] 

124 

125 parent_subparsers = plugins.call_plugin("birdplan.plugins.cmdline.bgp.peer", "get_subparsers", {}) 

126 

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 ) 

136 

137 subparser.add_argument( 

138 "--only", 

139 nargs=1, 

140 default=None, 

141 metavar="ONLY", 

142 help="Limit output to: AS<NUMBER>", 

143 ) 

144 

145 # Set our internal subparser property 

146 self._subparser = subparser 

147 self._subparsers = None 

148 

149 def cmd_bgp_peer_summary(self, args: Any) -> Any: # pylint: disable=unused-argument 

150 """ 

151 Commandline handler for "bgp peer summary" action. 

152 

153 Parameters 

154 ---------- 

155 args : Dict[str, Any] 

156 Method argument(s). 

157 

158 """ 

159 

160 if not self._subparser: # pragma: no cover 

161 raise RuntimeError() 

162 

163 cmdline: BirdPlanCommandLine = args["cmdline"] 

164 

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] 

174 

175 # Grab Bird control socket 

176 bird_socket = cmdline.args.bird_socket[0] 

177 

178 # Suppress info output 

179 cmdline.birdplan.birdconf.birdconfig_globals.suppress_info = True 

180 

181 # Load BirdPlan configuration using the cache 

182 cmdline.birdplan_load_config(ignore_irr_changes=True, ignore_peeringdb_changes=True, use_cached=True) 

183 

184 # Grab peer list 

185 peer_list: BirdPlanBGPPeerSummary = cmdline.birdplan.state_bgp_peer_summary(bird_socket=bird_socket) 

186 

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:])} 

190 

191 return BirdPlanCmdlineBGPPeerShowResult(peer_list)