#! /usr/bin/env python3 """ discovery-wrapper A small tool which wraps around discovery and tries to guide the discovery process with a more modern approach with a Queue and workers. Based on the original version of poller-wrapper.py by Job Snijders Author: Neil Lathwood Orsiris de Jong Date: Oct 2019 Usage: This program accepts one command line argument: the number of threads that should run simultaneously. If no argument is given it will assume a default of 1 thread. Ubuntu Linux: apt-get install python-mysqldb FreeBSD: cd /usr/ports/*/py-MySQLdb && make install clean RHEL 7: yum install MySQL-python RHEL 8: dnf install mariadb-connector-c-devel gcc && python -m pip install mysqlclient Tested on: Python 3.6.8 / PHP 7.2.11 / CentOS 8 License: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. LICENSE.txt contains a copy of the full GPLv3 licensing conditions. """ import LibreNMS.library as LNMS try: import json import os import queue import subprocess import sys import threading import time from optparse import OptionParser except ImportError as exc: print('ERROR: missing one or more of the following python modules:') print('threading, queue, sys, subprocess, time, os, json') print('ERROR: %s' % exc) sys.exit(2) APP_NAME = "discovery_wrapper" LOG_FILE = "logs/" + APP_NAME + ".log" _DEBUG = False distdisco = False real_duration = 0 discovered_devices = 0 # (c) 2015, GPLv3, Daniel Preussker << << <<> /dev/null" command = "/usr/bin/env php %s -h %s %s 2>&1" % (discovery_path, device_id, output) # TODO: Replace with command_runner subprocess.check_call(command, shell=True) elapsed_time = int(time.time() - start_time) print_queue.put([threading.current_thread().name, device_id, elapsed_time]) except (KeyboardInterrupt, SystemExit): raise except: pass poll_queue.task_done() if __name__ == '__main__': logger = LNMS.logger_get_logger(LOG_FILE, debug=_DEBUG) install_dir = os.path.dirname(os.path.realpath(__file__)) LNMS.check_for_file(install_dir + '/.env') config = json.loads(LNMS.get_config_data(install_dir)) discovery_path = config['install_dir'] + '/discovery.php' log_dir = config['log_dir'] # (c) 2015, GPLv3, Daniel Preussker << << << << 0: try: time.sleep(1) nodes = memc.get("discovery.nodes") except: pass print("Clearing Locks") x = minlocks while x <= maxlocks: memc.delete('discovery.device.' + str(x)) x = x + 1 print("%s Locks Cleared" % x) print("Clearing Nodes") memc.delete("discovery.master") memc.delete("discovery.nodes") else: memc.decr("discovery.nodes") print("Finished %s." % time.time()) # EOC6 show_stopper = False if total_time > 21600: print("WARNING: the process took more than 6 hours to finish, you need faster hardware or more threads") print("INFO: in sequential style discovery the elapsed time would have been: %s seconds" % real_duration) for device in per_device_duration: if per_device_duration[device] > 3600: print("WARNING: device %s is taking too long: %s seconds" % (device, per_device_duration[device])) show_stopper = True if show_stopper: print("ERROR: Some devices are taking more than 3600 seconds, the script cannot recommend you what to do.") else: recommend = int(total_time / 300.0 * amount_of_workers + 1) print( "WARNING: Consider setting a minimum of %d threads. (This does not constitute professional advice!)" % recommend) sys.exit(2)