Refactoring: Changed remaining check parameters starting with an 's' to the new rules...
[check_mk.git] / cmk / ec / settings.py
blob9be17e9ffd65ac75c5498e83fce87c62166c7ad1
1 #!/usr/bin/env python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
26 """Settings handling for the Check_MK event console."""
28 from __future__ import print_function
30 # For some background about various design decisions below, see the concise
31 # but excellent article "Parsing Command Line Arguments" in the FPComplete blog
32 # at https://www.fpcomplete.com/blog/2017/12/parsing-command-line-arguments.
34 # NOTE: pylint/astroid doesn't fully understand typing annotations and the
35 # typing module yet, so we may have to suppress some things, see e.g. the
36 # issues https://github.com/PyCQA/pylint/issues/1063 for unused-import and
37 # https://github.com/PyCQA/pylint/issues/1290 for invalid-name.
39 from argparse import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter
40 from typing import List, NamedTuple, Optional, Union # pylint: disable=unused-import
42 from pathlib2 import Path
44 # a filesystem path with a user-presentable description
45 AnnotatedPath = NamedTuple('AnnotatedPath', [('description', str), ('value', Path)])
47 # filesystem paths related to the event console
48 Paths = NamedTuple('Paths', [
49 ('main_config_file', AnnotatedPath),
50 ('config_dir', AnnotatedPath),
51 ('rule_pack_dir', AnnotatedPath),
52 ('mkp_rule_pack_dir', AnnotatedPath),
53 ('unix_socket', AnnotatedPath),
54 ('event_socket', AnnotatedPath),
55 ('event_pipe', AnnotatedPath),
56 ('pid_file', AnnotatedPath),
57 ('log_file', AnnotatedPath),
58 ('history_dir', AnnotatedPath),
59 ('messages_dir', AnnotatedPath),
60 ('master_config_file', AnnotatedPath),
61 ('slave_status_file', AnnotatedPath),
62 ('spool_dir', AnnotatedPath),
63 ('status_file', AnnotatedPath),
64 ('status_server_profile', AnnotatedPath),
65 ('event_server_profile', AnnotatedPath),
66 ('compiled_mibs_dir', AnnotatedPath),
67 ('mongodb_config_file', AnnotatedPath),
71 def _default_paths(omd_root, default_config_dir):
72 # type: (Path, Path) -> Paths
73 """Returns all default filesystem paths related to the event console"""
74 run_dir = omd_root / 'tmp/run/mkeventd'
75 state_dir = omd_root / 'var/mkeventd'
76 return Paths(
77 main_config_file=AnnotatedPath('main configuration', default_config_dir / 'mkeventd.mk'),
78 config_dir=AnnotatedPath('configuration directory', default_config_dir / 'mkeventd.d'),
79 rule_pack_dir=AnnotatedPath('rule pack directory',
80 default_config_dir / 'mkeventd.d' / 'wato'),
81 mkp_rule_pack_dir=AnnotatedPath('rule pack export directory',
82 default_config_dir / 'mkeventd.d' / 'mkp' / 'rule_packs'),
83 unix_socket=AnnotatedPath('Unix socket', run_dir / 'status'),
84 event_socket=AnnotatedPath('event socket', run_dir / 'eventsocket'),
85 event_pipe=AnnotatedPath('event pipe', run_dir / 'events'),
86 pid_file=AnnotatedPath('PID file', run_dir / 'pid'),
87 log_file=AnnotatedPath('log file', omd_root / 'var/log/mkeventd.log'),
88 history_dir=AnnotatedPath('history directory', state_dir / 'history'),
89 messages_dir=AnnotatedPath('messages directory', state_dir / 'messages'),
90 master_config_file=AnnotatedPath('master configuraion', state_dir / 'master_config'),
91 slave_status_file=AnnotatedPath('slave status', state_dir / 'slave_status'),
92 spool_dir=AnnotatedPath('spool directory', state_dir / 'spool'),
93 status_file=AnnotatedPath('status file', state_dir / 'status'),
94 status_server_profile=AnnotatedPath('status server profile',
95 state_dir / 'StatusServer.profile'),
96 event_server_profile=AnnotatedPath('event server profile',
97 state_dir / 'EventServer.profile'),
98 compiled_mibs_dir=AnnotatedPath('compiled MIBs directory',
99 omd_root / 'local/share/check_mk/compiled_mibs'),
100 mongodb_config_file=AnnotatedPath('MongoDB configuration', omd_root / 'etc/mongodb.conf'))
103 # a network port number
104 PortNumber = NamedTuple('PortNumber', [('value', int)])
106 # network port numbers related to the event console
107 PortNumbers = NamedTuple('PortNumbers', [
108 ('syslog_udp', PortNumber),
109 ('syslog_tcp', PortNumber),
110 ('snmptrap_udp', PortNumber),
114 def _default_port_numbers():
115 # type: () -> PortNumbers
116 """Returns all port numbers related to the event console"""
117 return PortNumbers(
118 syslog_udp=PortNumber(514), syslog_tcp=PortNumber(514), snmptrap_udp=PortNumber(162))
121 # a Unix file descriptor number
122 FileDescriptor = NamedTuple('FileDescriptor', [('value', int)])
125 class ECArgumentParser(ArgumentParser):
126 """An argument parser for the event console"""
128 def __init__(self, prog, version, paths, port_numbers):
129 # type: (str, str, Paths, PortNumbers) -> None
130 super(ECArgumentParser, self).__init__(
131 prog=prog,
132 formatter_class=RawDescriptionHelpFormatter,
133 description='Start the Check_MK event console.',
134 epilog=self._epilog(paths))
135 self._add_arguments(version, port_numbers)
137 @staticmethod
138 def _epilog(paths):
139 # type: (Paths) -> str
140 width = max([len(p.description) for p in paths]) + 1 # for colon
141 return ('Paths used by the event console:\n\n' + '\n'.join(
142 ' {:<{width}} {}'.format(p.description + ':', p.value, width=width) for p in paths))
144 def _add_arguments(self, version, port_numbers):
145 # type: (str, PortNumbers) -> None
146 self.add_argument(
147 '-V', '--version', action='version', version='%(prog)s version ' + version)
148 self.add_argument('-v', '--verbose', action='count', default=0, help='increase verbosity')
149 self.add_argument('--syslog', action='store_true', help='enable built-in UDP syslog server')
150 self.add_argument(
151 '--syslog-fd',
152 metavar='FD',
153 type=self._file_descriptor,
154 help=('use the given file descriptor instead of UDP port %d' %
155 port_numbers.syslog_udp.value))
156 self.add_argument(
157 '--syslog-tcp', action='store_true', help='enable built-in TCP syslog server')
158 self.add_argument(
159 '--syslog-tcp-fd',
160 metavar='FD',
161 type=self._file_descriptor,
162 help=('use the given file descriptor instead of TCP port %d' %
163 port_numbers.syslog_tcp.value))
164 self.add_argument('--snmptrap', action='store_true', help='enable built-in snmptrap server')
165 self.add_argument(
166 '--snmptrap-fd',
167 metavar='FD',
168 type=self._file_descriptor,
169 help=('use the given file descriptor instead of UDP port %d' %
170 port_numbers.snmptrap_udp.value))
171 self.add_argument(
172 '-g',
173 '--foreground',
174 action='store_true',
175 help='run in the foreground instead of daemonizing')
176 self.add_argument(
177 '-d',
178 '--debug',
179 action='store_true',
180 help='enable debug mode, letting exceptions through')
181 self.add_argument(
182 '--profile-status',
183 action='store_true',
184 help='create performance profile for status thread')
185 self.add_argument(
186 '--profile-event',
187 action='store_true',
188 help='create performance profile for event thread')
190 @staticmethod
191 def _file_descriptor(value):
192 # type: (str) -> FileDescriptor
193 """A custom argument type for file descriptors, i.e. non-negative integers"""
194 try:
195 file_desc = int(value)
196 if file_desc < 0:
197 raise ValueError
198 except ValueError:
199 raise ArgumentTypeError('invalid file descriptor value: %r' % value)
200 return FileDescriptor(file_desc)
203 # a communication endpoint, e.g. for syslog or SNMP
204 EndPoint = Union[PortNumber, FileDescriptor] # pylint: disable=invalid-name
207 def _endpoint(enabled, file_descriptor, default_port_number):
208 # type: (bool, FileDescriptor, PortNumber) -> Optional[EndPoint]
209 """Returns a communication endpoint based on given commandline arguments"""
210 if not enabled:
211 return None
212 if file_descriptor is None:
213 return default_port_number
214 return file_descriptor
217 # various post-processed commandline options
218 Options = NamedTuple('Options', [
219 ('verbosity', int),
220 ('syslog_udp', Optional[EndPoint]),
221 ('syslog_tcp', Optional[EndPoint]),
222 ('snmptrap_udp', Optional[EndPoint]),
223 ('foreground', bool),
224 ('debug', bool),
225 ('profile_status', bool),
226 ('profile_event', bool),
229 # all settings of the event console
230 Settings = NamedTuple('Settings', [
231 ('paths', Paths),
232 ('options', Options),
236 def settings(version, omd_root, default_config_dir, argv):
237 # type: (str, Path, Path, List[str]) -> Settings
238 """Returns all event console settings"""
239 paths = _default_paths(omd_root, default_config_dir)
240 port_numbers = _default_port_numbers()
241 parser = ECArgumentParser(Path(argv[0]).name, version, paths, port_numbers)
242 args = parser.parse_args(argv[1:])
243 options = Options(
244 verbosity=args.verbose,
245 syslog_udp=_endpoint(args.syslog, args.syslog_fd, port_numbers.syslog_udp),
246 syslog_tcp=_endpoint(args.syslog_tcp, args.syslog_tcp_fd, port_numbers.syslog_tcp),
247 snmptrap_udp=_endpoint(args.snmptrap, args.snmptrap_fd, port_numbers.snmptrap_udp),
248 foreground=args.foreground,
249 debug=args.debug,
250 profile_status=args.profile_status,
251 profile_event=args.profile_event)
252 return Settings(paths=paths, options=options)
255 if __name__ == "__main__":
256 import sys
257 import cmk
258 import cmk.utils.paths
259 print(settings(cmk.__version__, Path(cmk.utils.paths.omd_root),
260 Path(cmk.utils.paths.default_config_dir), sys.argv))