Coverage for birdplan/plugins/cmdline/monitor.py: 59%

49 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 "birdplan monitor".""" 

20 

21 

22import argparse 

23import json 

24import logging 

25from typing import Any, Dict, Optional 

26 

27from ...cmdline import BIRDPLAN_MONITOR_FILE, BirdPlanCommandLine, BirdPlanCommandlineResult 

28from ...exceptions import BirdPlanError 

29from .cmdline_plugin import BirdPlanCmdlinePluginBase 

30 

31__all__ = ["BirdPlanCmdlineMonitor"] 

32 

33 

34class BirdPlanCmdlineMonitor(BirdPlanCmdlinePluginBase): 

35 """BirdPlan "configure" command.""" 

36 

37 # Output filename 

38 _output_filename: Optional[str] 

39 

40 def __init__(self) -> None: 

41 """Initialize object.""" 

42 

43 super().__init__() 

44 

45 # Plugin setup 

46 self.plugin_description = "birdplan monitor" 

47 self.plugin_order = 10 

48 

49 self._output_filename = None 

50 

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

52 """ 

53 Register commandline parsers. 

54 

55 Parameters 

56 ---------- 

57 args : Dict[str, Any] 

58 Method argument(s). 

59 

60 """ 

61 

62 root_parser = args["root_parser"] 

63 

64 # CMD: configure 

65 subparser = root_parser.add_parser("monitor", help="Monitor BIRD status") 

66 

67 subparser.add_argument( 

68 "--action", 

69 action="store_const", 

70 const="monitor", 

71 default="monitor", 

72 help=argparse.SUPPRESS, 

73 ) 

74 

75 # Output filename 

76 subparser.add_argument( 

77 "-o", 

78 "--output-file", 

79 nargs=1, 

80 metavar="MONITOR_OUTPUT_FILE", 

81 default=[BIRDPLAN_MONITOR_FILE], 

82 help=f"Monitor filename to output to, using '-' will output to stdout (default: {BIRDPLAN_MONITOR_FILE})", 

83 ) 

84 

85 # Set our internal subparser property 

86 self._subparser = subparser 

87 self._subparsers = None 

88 

89 def cmd_monitor(self, args: Any) -> Any: 

90 """ 

91 Commandline handler for "monitor" action. 

92 

93 Parameters 

94 ---------- 

95 args : Dict[str, Any] 

96 Method argument(s). 

97 

98 """ 

99 

100 cmdline: BirdPlanCommandLine = args["cmdline"] 

101 

102 # Grab Bird control socket 

103 bird_socket = cmdline.args.bird_socket[0] 

104 

105 # Suppress info output 

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

107 

108 # Load BirdPlan configuration 

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

110 

111 # Save the output filename 

112 self.output_filename = cmdline.args.output_file[0] 

113 

114 # Grab information to return 

115 bgp_protocol = cmdline.birdplan.state_bgp_peer_summary(bird_socket=bird_socket) 

116 ospf_protocol = cmdline.birdplan.state_ospf_summary(bird_socket=bird_socket) 

117 

118 # Build structure 

119 monitor_status = { 

120 "bgp": bgp_protocol, 

121 "ospf": ospf_protocol, 

122 } 

123 

124 # If we're outputting to file, write it here 

125 if self.output_filename and self.output_filename != "-": 

126 self._write_monitor_file(monitor_status) 

127 return BirdPlanCommandlineResult(monitor_status, has_console_output=False) 

128 

129 return BirdPlanCommandlineResult(monitor_status) 

130 

131 def _write_monitor_file(self, data: Any) -> None: 

132 """ 

133 Write out monitor file with data. 

134 

135 Parameters 

136 ---------- 

137 data : str 

138 Monitor data. 

139 

140 """ 

141 

142 if not self.output_filename: 

143 raise RuntimeError("Attribute 'output_filename' must be set") 

144 

145 # Write out config file 

146 try: 

147 with open(self.output_filename, "w", encoding="UTF-8") as config_file: 

148 # Write out data json 

149 logging.debug("Writing monitor file '%s'", self.output_filename) 

150 config_file.write(json.dumps(data, indent=4, sort_keys=True)) 

151 except OSError as err: # pragma: no cover 

152 raise BirdPlanError(f"Failed to open '{self.output_filename}' for writing: {err}") from None 

153 

154 @property 

155 def output_filename(self) -> Optional[str]: 

156 """Config file name to write out.""" 

157 return self._output_filename 

158 

159 @output_filename.setter 

160 def output_filename(self, output_filename: str) -> None: 

161 """Config file name to write out.""" 

162 self._output_filename = output_filename