From 0d8ac6281bc1daa021b06b7c30d089a23738bb9e Mon Sep 17 00:00:00 2001 From: "th.l" <thl-cmk@outlook.com> Date: Tue, 28 Nov 2023 20:08:19 +0100 Subject: [PATCH] update project --- README.md | 2 +- bin/topology_data/create_topology_classes.py | 85 ++++++++++++++++++- bin/topology_data/create_topology_data.py | 15 ++-- mkp/create_topology_data-0.3.0-20231128.mkp | Bin 0 -> 12443 bytes packages/create_topology_data | 2 +- 5 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 mkp/create_topology_data-0.3.0-20231128.mkp diff --git a/README.md b/README.md index d771a66..3f1306f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.2.0-20231116.mkp "create_topology_data-0.2.0-20231116.mkp" +[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.3.0-20231128.mkp "create_topology_data-0.3.0-20231128.mkp" Network Visualization data creation tool from inventory data This script creates the topology data file needed for the [Checkmk Exchange Network visualization](https://exchange.checkmk.com/p/network-visualization) plugin by Andreas Boesl and [schnetz](https://exchange.checkmk.com/u/schnetz).\ diff --git a/bin/topology_data/create_topology_classes.py b/bin/topology_data/create_topology_classes.py index 2610ead..6b3a176 100755 --- a/bin/topology_data/create_topology_classes.py +++ b/bin/topology_data/create_topology_classes.py @@ -16,6 +16,8 @@ from typing import Dict, List, Any, NamedTuple from enum import Enum, unique from abc import abstractmethod from ast import literal_eval +import livestatus + from create_topology_utils import ( CREATE_TOPOLOGY_VERSION, @@ -186,7 +188,7 @@ class Settings: class HostCache: - def __init__(self): + def __init__(self, debug: bool = False): self.__cache = {} self.__inventory_pre_fetch_list: List[str] = [ PATH_INTERFACES, @@ -202,6 +204,7 @@ class HostCache: Returns: the inventory data as dictionary """ + raise NotImplementedError() @abstractmethod def get_interface_items(self, host: str, debug: bool = False) -> List: @@ -214,6 +217,7 @@ class HostCache: Returns: list of the interface items """ + raise NotImplementedError() def __fill_cache(self, host: str): # pre fill inventory data @@ -337,3 +341,82 @@ class HostCacheFileSystem(HostCache): return [] return __data + + +class HostCacheMultiSite(HostCache): + def __init__(self, debug: bool = False): + super().__init__(debug=debug) + self.__sites = {} + self.get_sites(debug=debug) + self.__c = livestatus.MultiSiteConnection(self.__sites) + # self.__c.set_prepend_site(False) # is default + # self.__c.parallelize = True # is default + self.__dead_sites = [site['site']['alias'] for site in self.__c.dead_sites().values()] + if self.__dead_sites: + self.__dead_sites = ', '.join( self.__dead_sites) + print(f'WARNING: use of dead site(s) {self.__dead_sites} is disabled') + self.__c.set_only_sites(self.__c.alive_sites()) + + def get_sites(self, debug: bool = False): + sites_mk = Path(f'{OMD_ROOT}/etc/check_mk/multisite.d/sites.mk') + socket_path = f'unix:{OMD_ROOT}/tmp/run/live' + if sites_mk.exists(): + # make eval() "secure" + # https://realpython.com/python-eval-function/#minimizing-the-security-issues-of-eval + _code = compile(sites_mk.read_text(), "<string>", "eval") + allowed_names = ['sites', 'update'] + for name in _code.co_names: + if name not in allowed_names: + raise NameError(f'Use of {name} in {sites_mk.name} not allowed.') + + sites_raw = {} + eval(sites_mk.read_text(), {"__builtins__": {}}, {"sites": sites_raw}) + + for site, data in sites_raw.items(): + self.__sites[site] = { + 'alias': data['alias'], + 'timeout': data['timeout'], + 'nagios_url': '/nagios/', + } + if data['socket'] == ('local', None): + self.__sites[site]['socket'] = socket_path + else: + protocol, socket = data['socket'] + address, port = socket['address'] + self.__sites[site]['socket'] = f'{protocol}:{address}:{port}' + self.__sites[site]['tls'] = socket['tls'] + if debug: + print(f'Multisite: Site {site} found, ' + f'Socket: {self.__sites[site]["socket"]}, ' + f'TLS: {self.__sites[site].get("tls", "N/A")}.') + + def get_inventory_data(self, host: str, debug: bool = False) -> Dict[str, str] | None: + query = f'GET hosts\nColumns: mk_inventory\nOutputFormat: python3\nFilter: host_name = {host}\n' + data = self.__c.query(query=query) + if data: + try: + data = literal_eval(data[0][0].decode('utf-8')) + except SyntaxError as e: + if debug: + print(f'data: |{data}|') + print(f'type: {type(data)}') + print(f'exception: {e}') + return + return data + + def get_interface_items(self, host: str, debug: bool = False) -> List: + query = ( + 'GET services\n' + 'Columns: host_name description check_command\n' + 'Filter: description ~ Interface\n' + f'Filter: host_name = {host}\n' + 'OutputFormat: python3\n' + ) + data = self.__c.query(query=query) + items = [] + for host, description, check_command in data: + items.append(description[10:]) # remove 'Interface ' from description + + if debug: + print(f'Interfaces items found: {len(items)} an host {host}') + return items diff --git a/bin/topology_data/create_topology_data.py b/bin/topology_data/create_topology_data.py index e3c6627..d3caccd 100755 --- a/bin/topology_data/create_topology_data.py +++ b/bin/topology_data/create_topology_data.py @@ -38,12 +38,12 @@ # 2023-11-16: added option -b/--backend [LIVESTATUS, FILESYSTEM], # LIVESTATUS is the default for performance reasons -> for now only local site # FILESYSTEM fethches the data directly form the inventory files -> use in distributed environments - +# 2023-11-28: added MULTISITE as backend, via livestatus # -# PoC for creating topology_data.json from inventory data +# creating topology_data.json from inventory data # # This script creates the topology data file needed for the Checkmk "network_visualization" plugin by -# Andreas Boesl and schnetz. For more information see +# Andreas Boesl/schnetz. For more information see # https://forum.checkmk.com/t/network-visualization/41680 # https://exchange.checkmk.com/p/network-visualization # @@ -76,6 +76,7 @@ from create_topology_classes import ( StaticConnection, HostCacheLiveStatus, HostCacheFileSystem, + HostCacheMultiSite, CacheItems, ) @@ -275,18 +276,20 @@ def create_topology( if __name__ == '__main__': start_time = time_ns() SETTINGS = Settings(vars(parse_arguments())) + print() + print(f'Start time: {strftime(SETTINGS.time_format)}') + match SETTINGS.backend: case 'LIVESTATUS': HOST_CACHE = HostCacheLiveStatus() case 'FILESYSTEM': HOST_CACHE = HostCacheFileSystem() + case 'MULTISITE': + HOST_CACHE = HostCacheMultiSite(debug=SETTINGS.debug) case _: print(f'Backend {SETTINGS.backend} not (yet) implemented') exit() - print() - print(f'Start time: {strftime(SETTINGS.time_format)}') - user_data = get_data_from_toml(file=SETTINGS.user_data_file) HOST_MAP = user_data.get('HOST_MAP', {}) DROP_HOSTS = user_data.get('DROP_HOSTS', []) diff --git a/mkp/create_topology_data-0.3.0-20231128.mkp b/mkp/create_topology_data-0.3.0-20231128.mkp new file mode 100644 index 0000000000000000000000000000000000000000..c56f1b9d2510820ca71ec418fcf8ed95361ddc67 GIT binary patch literal 12443 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 Z!{_1i@Ok(=eE$7D{|7X0Dl-7^006%BZ2<rP literal 0 HcmV?d00001 diff --git a/packages/create_topology_data b/packages/create_topology_data index 3675ee3..9c199bf 100644 --- a/packages/create_topology_data +++ b/packages/create_topology_data @@ -59,7 +59,7 @@ 'topology_data/create_topology_args.py']}, 'name': 'create_topology_data', 'title': 'Network Visualization data creation', - 'version': '0.2.0-20231116', + 'version': '0.3.0-20231128', 'version.min_required': '2.2.0p1', 'version.packaged': '2.2.0p14', 'version.usable_until': '2.3.0p1'} -- GitLab