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
« 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 "birdplan monitor"."""
22import argparse
23import json
24import logging
25from typing import Any, Dict, Optional
27from ...cmdline import BIRDPLAN_MONITOR_FILE, BirdPlanCommandLine, BirdPlanCommandlineResult
28from ...exceptions import BirdPlanError
29from .cmdline_plugin import BirdPlanCmdlinePluginBase
31__all__ = ["BirdPlanCmdlineMonitor"]
34class BirdPlanCmdlineMonitor(BirdPlanCmdlinePluginBase):
35 """BirdPlan "configure" command."""
37 # Output filename
38 _output_filename: Optional[str]
40 def __init__(self) -> None:
41 """Initialize object."""
43 super().__init__()
45 # Plugin setup
46 self.plugin_description = "birdplan monitor"
47 self.plugin_order = 10
49 self._output_filename = None
51 def register_parsers(self, args: Dict[str, Any]) -> None:
52 """
53 Register commandline parsers.
55 Parameters
56 ----------
57 args : Dict[str, Any]
58 Method argument(s).
60 """
62 root_parser = args["root_parser"]
64 # CMD: configure
65 subparser = root_parser.add_parser("monitor", help="Monitor BIRD status")
67 subparser.add_argument(
68 "--action",
69 action="store_const",
70 const="monitor",
71 default="monitor",
72 help=argparse.SUPPRESS,
73 )
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 )
85 # Set our internal subparser property
86 self._subparser = subparser
87 self._subparsers = None
89 def cmd_monitor(self, args: Any) -> Any:
90 """
91 Commandline handler for "monitor" action.
93 Parameters
94 ----------
95 args : Dict[str, Any]
96 Method argument(s).
98 """
100 cmdline: BirdPlanCommandLine = args["cmdline"]
102 # Grab Bird control socket
103 bird_socket = cmdline.args.bird_socket[0]
105 # Suppress info output
106 cmdline.birdplan.birdconf.birdconfig_globals.suppress_info = True
108 # Load BirdPlan configuration
109 cmdline.birdplan_load_config(ignore_irr_changes=True, ignore_peeringdb_changes=True, use_cached=True)
111 # Save the output filename
112 self.output_filename = cmdline.args.output_file[0]
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)
118 # Build structure
119 monitor_status = {
120 "bgp": bgp_protocol,
121 "ospf": ospf_protocol,
122 }
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)
129 return BirdPlanCommandlineResult(monitor_status)
131 def _write_monitor_file(self, data: Any) -> None:
132 """
133 Write out monitor file with data.
135 Parameters
136 ----------
137 data : str
138 Monitor data.
140 """
142 if not self.output_filename:
143 raise RuntimeError("Attribute 'output_filename' must be set")
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
154 @property
155 def output_filename(self) -> Optional[str]:
156 """Config file name to write out."""
157 return self._output_filename
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