Last active
August 29, 2015 14:05
-
-
Save rc5hack/34a68d464a76fd32df5f to your computer and use it in GitHub Desktop.
4yandex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os, sys, commands | |
import argparse | |
import ConfigParser | |
version = '0.1.1' | |
default_monitoring_checks_cache_path = '/var/cache/monitoring' | |
def createParser (): | |
parser = argparse.ArgumentParser( | |
prog = 'custom-monitoring-checks-helper', | |
description = '''Helper Python script to handle custom monitoring checks. | |
Checks are defined with config files (one for each). | |
Each check could be forced to run and display it's actual status, | |
or all checks latest statuses could be displayed from cache. | |
If there are no cached data for one of the checks, this check | |
would be also forced to run in order to retrieve it's status.''', | |
epilog = '''(c) Antonio Kless 2014. | |
This software is available under BSD license.''' | |
) | |
parser.add_argument('-a', '--all', action='store_true', default=False, help='show all checks latest statuses (show cached status, or cause a new check run if no cached data found)') | |
parser.add_argument('-f', '--force-check', help="force check run and show it's actual status", metavar='CHECK_NAME') | |
parser.add_argument('-s', '--show', help='show config details for the check specified', metavar='CHECK_NAME') | |
parser.add_argument('-d', '--config-file-scan-dir', default='./custom-monitoring-checks.d', help='specify a directory where config files should be looked for (default - ./custom-monitoring-checks.d)', metavar='DIR') | |
parser.add_argument('-V', '--version', action='version', version='%(prog)s {}'.format(version), help='show version and exit') | |
return parser | |
def config_file_scan_dir (dirname): | |
if (os.path.exists(dirname)): | |
files_found = os.listdir(dirname) | |
if (len(files_found)) < 1: | |
sys.stderr.write("No config files found in " + dirname + " - don't know what to do, aborting.\n") | |
sys.exit(1) | |
checks = {} | |
for config_file in files_found: | |
check = config_file_parse(config_file) | |
if check: | |
checks.update(check) | |
if (len(checks)) < 1: | |
sys.stderr.write("No valid config files found, no checks loaded, exiting.\n") | |
sys.exit(0) | |
print('Now ' + format(len(checks)) + ' check(s) loaded.') | |
return checks | |
else: | |
sys.stderr.write("Directory " + dirname + " does not exist or not accessable, aborting.\n") | |
sys.exit(1) | |
def config_file_parse (filename): | |
print('Found config file: ' + filename) | |
config = ConfigParser.ConfigParser() | |
config.readfp(open(args.config_file_scan_dir + '/' + filename)) | |
#TODO: config values validation needed | |
try: | |
parsed_config = { | |
config.get('check', 'name'): { | |
'path': config.get('check', 'path'), | |
'description': config.get('check', 'description'), | |
'cronstring': config.get('check', 'cronstring'), | |
'cache': config.get('check', 'cache') | |
} | |
} | |
print(' ...successfully parsed config for check "' + config.get('check', 'name') + '"') | |
return parsed_config | |
except BaseException: | |
print(' ...not a valid config file, skipping') | |
def read_check_status_from_cache (filename, checkname): | |
#FIXME: f.read() is danger to use as it may causes memory overflow | |
if (os.path.exists(filename)): | |
try: | |
f = open(filename, 'r') | |
except IOError: | |
pass | |
else: | |
content = f.read() | |
f.close() | |
if (len(content) > 1): | |
return content | |
backupfilename = default_monitoring_checks_cache_path + '/' + checkname + '.last-run' | |
if (os.path.exists(backupfilename)): | |
try: | |
f = open(backupfilename, 'r') | |
except IOError: | |
pass | |
else: | |
content = f.read() | |
f.close() | |
if (len(content) > 1): | |
return content | |
return False | |
if __name__ == '__main__': | |
parser = createParser() | |
if (len(sys.argv)) < 2: | |
sys.stderr.write("No arguments passed - don't know what to do, aborting.\n") | |
print("\n") | |
parser.print_help() | |
sys.exit(1) | |
args = parser.parse_args() | |
checks = config_file_scan_dir(args.config_file_scan_dir) | |
print("\n") | |
if (args.show): | |
if (args.show in checks): | |
print('Config details for check "' + args.show + '":') | |
print(' command to execute or path to executable file: ' + checks[args.show]['path']) | |
print(' check description: ' + checks[args.show]['description']) | |
print(' scheduling string for cron job: ' + checks[args.show]['cronstring']) | |
print(' latest check status should be stored to: ' + checks[args.show]['cache']) | |
else: | |
sys.stderr.write("No such check found - " + args.show + ", aborting.\n") | |
sys.exit(1) | |
elif (args.force_check): | |
if (args.force_check in checks): | |
print('Force run for check "' + args.force_check + '":') | |
print(commands.getoutput(checks[args.force_check]['path'])) | |
else: | |
sys.stderr.write("No such check found - " + args.force_check + ", aborting.\n") | |
sys.exit(1) | |
elif (args.all): | |
for check in checks: | |
print('Latest value for check "' + check + '":') | |
data_from_cache = read_check_status_from_cache(checks[check]['cache'], check) | |
if (data_from_cache): | |
print ' ...cached data available:' | |
print data_from_cache | |
else: | |
print ' ...cached data unavailable, force check run:' | |
print(commands.getoutput(checks[check]['path'])) | |
else: | |
sys.stderr.write("Not enough arguments passed - don't know what to do, aborting.\n") | |
print("\n") | |
parser.print_help() | |
sys.exit(1) | |
#TODO: when processing --force_check or --all, it's better to format check's status output to some human-friendly view |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[check] | |
name = new_os_updates_available | |
path = /opt/scripts/monitoring/new-os-updates-available.sh | |
description = Returns 1, if there are some new OS updates available to install, and 0 instead | |
cronstring = */30 * * * * | |
cache = /any/custom/path/to/cache/new-os-updates-available.last-run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment