def main(): client = Client(['localhost']) plugins = client.get_plugins([[args.plugin]]) # No plugin found if not plugins: nagios.exit_unknown("plugin %s not found" % args.plugin) if args.force: plugins = client.force_run(plugins, progress=False) # Manage plugin result. We can't return much data to Nagios, so just say if it's alright or not for plugin in plugins.values()[0]['plugins'].itervalues(): if not plugin['lastResult']: # No result?! -> UNKNOWN nagios.exit_unknown("plugin has no last result") elif plugin['lastResult']['status'] == 'OK': try: nagios.exit_ok(plugin['lastResult']['messages']['ok'][0]) except (KeyError, IndexError, TypeError): nagios.exit_ok("smoke test succeeded at %s" % plugin['lastResult']['lastRun']) elif plugin['lastResult']['status'] == 'WARN': try: nagios.exit_warning(plugin['lastResult']['messages']['warn'][0]) except (KeyError, IndexError, TypeError): nagios.exit_warning("smoke test returned warnings at %s" % plugin['lastResult']['lastRun']) elif plugin['lastResult']['status'] == 'ERROR': try: nagios.exit_critical(plugin['lastResult']['messages']['error'][0]) except (KeyError, IndexError, TypeError): nagios.exit_critical("smoke test failed at %s" % plugin['lastResult']['lastRun']) else: nagios.exit_unknown("unknown status %s at %s" % (plugin['lastResult']['status'], plugin['lastResult']['lastRun']))
def main(): """ Main entrance """ parser = argparse.ArgumentParser( description='Smoker client tool', add_help=False) # Action arguments group_action = parser.add_argument_group('Action switchers') group_action.add_argument( '-f', '--force', dest='force', action='store_true', help="Force plugins run (otherwise just print last results)") group_action.add_argument( '-l', '--list', dest='list', action='store_true', help="List plugins") group_action.add_argument( '-h', '--help', dest='help', action='store_true', help="Show this help and exit") # Host arguments group_main = parser.add_argument_group('Target host switchers') group_main.add_argument( '-s', '--hosts', dest='hosts', nargs='+', help="Hosts with running smokerd (default localhost)") # Filtering options # List of plugins group_filters = parser.add_argument_group('Filters') group_filters.add_argument( '-p', '--plugins', dest='plugins', nargs='+', help="Filter plugins by name") group_filters.add_argument( '--exclude-plugins', dest='exclude_plugins', nargs='+', help="Exclude plugins by names") # Other filters group_filters.add_argument( '--filter', dest='filter', default=[], nargs='+', help=("Filter plugins by it's parameters, " "eg. --filter 'Category connectors'")) group_filters.add_argument( '--exclude', action='store_true', help=("Negative filters (exclude) - currently works only " "for one filter")) group_filters.add_argument( '--category', help="Filter plugins by Category parameter") group_filters.add_argument( '--component', help="Filter plugins by Component parameter (eg. server)") group_filters.add_argument( '--health', action='store_true', help="Filter plugins by Type healthCheck") group_filters.add_argument( '--smoke', action='store_true', help="Filter plugins by Type smokeTest") # Plugin state filters group_filters.add_argument( '--filter-status', dest='filter_status', default=[], nargs='+', help="Filter plugins by it's state, eg. --filter-state ERROR WARN") group_filters.add_argument( '--nook', dest='state_nook', action='store_true', help=("Only non-OK plugins (ERROR, WARN, UNKNOWN). " "Can't be used together with --filter-state")) group_filters.add_argument( '--error', dest='state_error', action='store_true', help="Only ERROR. Can't be used together with --filter-state") group_filters.add_argument( '--warn', '--warning', dest='state_warn', action='store_true', help="Only WARN. Can't be used together with --filter-state") group_filters.add_argument( '--unknown', dest='state_unknown', action='store_true', help="Only UNKNOWN. Can't be used together with --filter-state") group_filters.add_argument( '--ok', dest='state_ok', action='store_true', help="Only OK. Can't be used together with --filter-state") # Output switchers group_output = parser.add_argument_group('Output switchers') group_output.add_argument( '-o', '--pretty', dest='pretty', default='normal', help=("Output format: minimal / normal / long / full / raw / json / " "tap / xml")) group_output.add_argument( '--no-colors', dest='no_colors', action='store_true', help="Don't use colors in output") group_output.add_argument( '--no-progress', dest='no_progress', action='store_true', help="Don't show progress bar") group_output.add_argument( '-v', '--verbose', dest='verbose', action='store_true', help="Be verbose") group_output.add_argument( '-d', '--debug', dest='debug', action='store_true', help="Debug output") group_output.add_argument( '--junit-config-file', dest='junit_config_file', help="Name of configuration file for junit xml formatter") _add_plugin_arguments(parser) args = parser.parse_args() # Set log level and set args.no_progress option if args.verbose: lg.setLevel(logging.INFO) args.no_progress = True if args.debug: lg.setLevel(logging.DEBUG) args.no_progress = True if args.help: parser.print_help() sys.exit(0) if args.pretty == 'minimal': # Minimal output (only host and errored plugins) if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '', 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR' : '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN' : '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = { 'OK' : '', 'WARN' : '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})', 'ERROR' : '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})', 'UNKNOWN' : '- {name:<32} [{lastResult[status]}]' } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [{status}]', 'ERROR' : ' -- {name:<30} [{status}]', 'UNKNOWN' : ' -- {name:<30} [{status}]', } format_plugin_msg = '' format_plugin_component_msg = '' format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'normal': # Normal output (host and it's plugins without component results) if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : '', 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : '', 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = { 'info' : '', 'warn' : ' [{level}] {msg}', 'error' : ' [{level}] {msg}', } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [{status}]', 'ERROR' : ' -- {name:<30} [{status}]', 'UNKNOWN' : ' -- {name:<30} [{status}]', } format_plugin_component_msg = { 'info' : '', 'warn' : ' [{level}] {msg}', 'error' : ' [{level}] {msg}', } format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'long': if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : ' -- {name:<30} [%(green)s{status}%(default)s]' % COLORS, 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = ' [{level}] {msg}' format_plugin_component = ' -- {name:<30} [{status}]' format_plugin_component_msg = ' [{level}] {msg}' format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'full': if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : ' -- {name:<30} [%(green)s{status}%(default)s]' % COLORS, 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = ' [{level}] {msg}' format_plugin_component = ' -- {name:<30} [{status}]' format_plugin_component_msg = ' [{level}] {msg}' format_plugin_run = ' Last run: {lastResult[lastRun]!s}\n Next run: {nextRun!s}' format_plugin_param = ' {key:<10} {value}' elif args.pretty in ['raw', 'json', 'tap', 'xml']: # Raw and special outputs doesn't need formatting pass else: lg.error("Invalid pretty output %s" % args.pretty) sys.exit(1) # Setup custom filters if args.category: args.filter.append('Category %s' % args.category) if args.component: args.filter.append('Component %s' % args.component) # Health checks and smoke tests together? Don't add filter if args.health or args.smoke: if args.health: args.filter.append('Type healthCheck') if args.smoke: args.filter.append('Type smokeTest') # Setup plugins filter filters = [] if args.filter: for f in args.filter: filter = {} try: filter = { 'key' : f.split(' ')[0], 'value': f.split(' ')[1] } except: lg.error("Invalid filter parameter format!") sys.exit(1) filters.append(filter) if filters and args.plugins: lg.warn("Plugin filter and plugin list used together. " "Only plugins matching both will be displayed.") if args.plugins: filters.append(args.plugins) # Setup state filters states = [] if args.filter_status: states = args.filter_status elif args.state_nook: states = ['ERROR', 'WARN', 'UNKNOWN'] else: if args.state_ok: states.append('OK') if args.state_error: states.append('ERROR') if args.state_warn: states.append('WARN') if args.state_unknown: states.append('UNKNOWN') # State list cannot be empty if not states: states = ['OK', 'ERROR', 'WARN', 'UNKNOWN'] # Add status filter filters.append(('status', states)) hosts = ['localhost'] discovered_hosts = _host_discovery(args) if args.hosts: hosts = args.hosts if discovered_hosts: hosts += discovered_hosts elif discovered_hosts: hosts = discovered_hosts # Initialize Client client = Client(hosts) plugins = client.get_plugins(filters, filters_negative=args.exclude, exclude_plugins=args.exclude_plugins) # No plugins found if not plugins: lg.error("No plugins found") sys.exit(1) # List plugins only (parameter --force is ignored) if args.list: plugins_tuple = plugins.get_host_plugins() if plugins.count_hosts() > 1: # We have more hosts than 1, print structure like: # server1/httpd # server2/crond for host, plugin in plugins_tuple: print "%s/%s" % (host['name'], plugin['name']) else: # Print only plugin-by-line structure without hostname for host, plugin in plugins_tuple: print "%s" % plugin['name'] sys.exit(0) # Force plugins run # set progress=False if --no-progress parameter is set if args.force: plugins = client.force_run( plugins, progress=not args.no_progress) # Print raw output if args.pretty == 'raw': from pprint import pprint pprint(plugins) sys.exit(0) elif args.pretty == 'json': # We need custom encoder to encode datetime objects class JSONEncoder(simplejson.JSONEncoder): """ JSON encoder that converts datetime.datetime object to isoformat string """ def default(self, obj): if isinstance(obj, datetime.datetime): return obj.isoformat() return simplejson.JSONEncoder.default(self, obj) print simplejson.dumps(plugins, cls=JSONEncoder) sys.exit(0) elif args.pretty == 'tap': dump = dump_tap(plugins) # Convert mixed string into ascii to workaround UnicodeEncodeError # shouldn't be needed in Python 3 print dump.encode('ascii', 'ignore') sys.exit(0) elif args.pretty == 'xml': dump = plugins_to_xml(plugins, args.junit_config_file) print dump sys.exit(0) # Print result output = [] hosts_printed = [] for host, plugin in plugins.get_host_plugins(): # Print host if not already printed if host['name'] not in hosts_printed: # Add empty line if any previous host if hosts_printed: output.append(" ") if isinstance(format_host, dict): output.append(format_host[host['status']].format(**host)) else: output.append(format_host.format(**host)) hosts_printed.append(host['name']) # Print plugin if not isinstance(plugin, dict): # Not a plugin continue if isinstance(format_plugin, basestring): output.append(format_plugin.format(**plugin)) else: output.append(format_plugin[plugin['lastResult']['status']].format(**plugin)) # Print last and next plugin run output.append(format_plugin_run.format(**plugin)) # Print last and next plugin run for key, value in plugin['parameters'].iteritems(): output.append(format_plugin_param.format(key=key, value=value)) # Print plugin messages if plugin['lastResult']['messages']: # For each message level for level, message in plugin['lastResult']['messages'].iteritems(): # For each message for msg in message: if isinstance(format_plugin_msg, basestring): output.append(format_plugin_msg.format(level=level, msg=msg.encode('utf8'))) else: output.append(format_plugin_msg[level].format(level=level, msg=msg.encode('utf8'))) # Print component result if plugin['lastResult']['componentResults']: for component in plugin['lastResult']['componentResults']: component = component['componentResult'] if isinstance(format_plugin_component, basestring): output.append(format_plugin_component.format(**component)) else: output.append(format_plugin_component[component['status']].format(**component)) # Print component messages if component['messages']: # For each message level for level, message in component['messages'].iteritems(): # For each message for msg in message: if isinstance(format_plugin_component_msg, basestring): output.append(format_plugin_component_msg.format(level=level, msg=msg.encode('utf8'))) else: output.append(format_plugin_component_msg[level].format(level=level, msg=msg.encode('utf8'))) for line in output: if line: print line
def main(): client = Client(['localhost']) plugins = None if args.plugin: if args.category or args.component or args.health: lg.warn( "Plugins specified by name, ignoring --category, --component and --health" ) plugins = client.get_plugins([args.plugin]) elif args.category or args.component or args.health: filter = [] if args.category: filter.append({'key': 'Category', 'value': args.category}) if args.component: filter.append({'key': 'Component', 'value': args.component}) if args.health: filter.append({'key': 'Type', 'value': 'healthCheck'}) plugins = client.get_plugins(filter) else: nagios.exit_unknown( "invalid startup configuration - neither plugin nor --category nor --component " "nor --health specified") # No plugin found if not plugins: if args.plugin: message = "plugin %s not found" % args.plugin else: message = "no plugin found by category %s and component %s, health: %s" % \ (args.category, args.component, args.health) nagios.exit_unknown(message) if args.force: plugins = client.force_run(plugins, progress=False) status_methods_pairs = [(ERROR, nagios.exit_critical), (UNKNOWN, nagios.exit_unknown), (WARN, nagios.exit_warning), (OK, nagios.exit_ok)] # Manage plugin result. We can't return much data to Nagios, so just say if it's alright or not results = dict((s, []) for s, _ in status_methods_pairs) for plugin in list(plugins.values())[0]['plugins'].itervalues(): plugin_name = plugin['name'] if not plugin['lastResult']: results[UNKNOWN].append({ 'name': plugin_name, 'message': "plugin has no last result" }) else: last_status = plugin['lastResult']['status'] if last_status in [ERROR, WARN, OK]: try: results[last_status].append({ 'name': plugin_name, 'message': plugin['lastResult']['messages'][last_status.lower()] [0] }) except (KeyError, IndexError, TypeError): if last_status == OK: results[last_status].append({ 'name': plugin_name, 'message': "smoke test %s succeeded at %s" % (plugin['name'], plugin['lastResult']['lastRun']) }) else: results[last_status].append({ 'name': plugin_name, 'message': parse_issue(plugin) }) else: results[UNKNOWN].append({ 'name': plugin_name, 'message': "unknown status %s at %s" % (plugin['lastResult']['status'], plugin['lastResult']['lastRun']) }) for status, exit_method in status_methods_pairs: if results[status]: if len(list(plugins.values())[0]['plugins']) == 1: # if only one plugin has been executed, do not print summary exit_method(results[status][0]['message']) else: summary = ', '.join([ "%s: %s" % (s, len(results[s])) for s, _ in status_methods_pairs if results[s] ]) messages = [ '\n'.join([ "%s - %s - %s" % (s, item['name'], item['message']) for item in list ]) for s, list in results.items() if list ] exit_method("%s\n%s" % (summary, '\n'.join(messages)))
def main(): """ Main entrance """ parser = argparse.ArgumentParser(description='Smoker client tool', add_help=False) # Action arguments group_action = parser.add_argument_group('Action switchers') group_action.add_argument('-f', '--force', dest='force', action='store_true', help="Force plugins run (otherwise just print last results)") group_action.add_argument('-l', '--list', dest='list', action='store_true', help="List plugins") group_action.add_argument('-h', '--help', dest='help', action='store_true', help="Show this help and exit") # Host arguments group_main = parser.add_argument_group('Target host switchers') group_main.add_argument('-s', '--hosts', dest='hosts', nargs='+', default=['localhost'], help="Hosts with running smokerd (default localhost)") # Filtering options # List of plugins group_filters = parser.add_argument_group('Filters') group_filters.add_argument('-p', '--plugins', dest='plugins', nargs='+', help="Filter plugins by names, can't be used with --filter option") group_filters.add_argument('--exclude-plugins', dest='exclude_plugins', nargs='+', help="Exclude plugins by names") # Other filters group_filters.add_argument('--filter', dest='filter', default=[], nargs='+', help="Filter plugins by it's parameters, eg. --filter 'Category connectors'") group_filters.add_argument('--exclude', action='store_true', help="Negative filters (exclude) - currently works only for one filter") group_filters.add_argument('--category', help="Filter plugins by Category parameter") group_filters.add_argument('--component', help="Filter plugins by Component parameter (eg. server)") group_filters.add_argument('--health', action='store_true', help="Filter plugins by Type healthCheck") group_filters.add_argument('--smoke', action='store_true', help="Filter plugins by Type smokeTest") # Plugin state filters group_filters.add_argument('--filter-status', dest='filter_status', default=[], nargs='+', help="Filter plugins by it's state, eg. --filter-state ERROR WARN") group_filters.add_argument('--nook', dest='state_nook', action='store_true', help="Only non-OK plugins (ERROR, WARN, UNKNOWN). Can't be used together with --filter-state") group_filters.add_argument('--error', dest='state_error', action='store_true', help="Only ERROR. Can't be used together with --filter-state") group_filters.add_argument('--warn', '--warning', dest='state_warn', action='store_true', help="Only WARN. Can't be used together with --filter-state") group_filters.add_argument('--unknown', dest='state_unknown', action='store_true', help="Only UNKNOWN. Can't be used together with --filter-state") group_filters.add_argument('--ok', dest='state_ok', action='store_true', help="Only OK. Can't be used together with --filter-state") # Output switchers group_output = parser.add_argument_group('Output switchers') group_output.add_argument('-o', '--pretty', dest='pretty', default='normal', help="Output format: minimal / normal / long / full / raw / json / tap") group_output.add_argument('--no-colors', dest='no_colors', action='store_true', help="Don't use colors in output") group_output.add_argument('--no-progress', dest='no_progress', action='store_true', help="Don't show progress bar") group_output.add_argument('-v', '--verbose', dest='verbose', action='store_true', help="Be verbose") group_output.add_argument('-d', '--debug', dest='debug', action='store_true', help="Debug output") args = parser.parse_args() # Set log level and set args.no_progress option if args.verbose: lg.setLevel(logging.INFO) args.no_progress = True if args.debug: lg.setLevel(logging.DEBUG) args.no_progress = True if args.help: parser.print_help() sys.exit(0) if args.pretty == 'minimal': # Minimal output (only host and errored plugins) if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '', 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR' : '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN' : '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = { 'OK' : '', 'WARN' : '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})', 'ERROR' : '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})', 'UNKNOWN' : '- {name:<32} [{lastResult[status]}]' } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [{status}]', 'ERROR' : ' -- {name:<30} [{status}]', 'UNKNOWN' : ' -- {name:<30} [{status}]', } format_plugin_msg = '' format_plugin_component_msg = '' format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'normal': # Normal output (host and it's plugins without component results) if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : '', 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : '', 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = { 'info' : '', 'warn' : ' [{level}] {msg}', 'error' : ' [{level}] {msg}', } format_plugin_component = { 'OK' : '', 'WARN' : ' -- {name:<30} [{status}]', 'ERROR' : ' -- {name:<30} [{status}]', 'UNKNOWN' : ' -- {name:<30} [{status}]', } format_plugin_component_msg = { 'info' : '', 'warn' : ' [{level}] {msg}', 'error' : ' [{level}] {msg}', } format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'long': if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : ' -- {name:<30} [%(green)s{status}%(default)s]' % COLORS, 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = ' [{level}] {msg}' format_plugin_component = ' -- {name:<30} [{status}]' format_plugin_component_msg = ' [{level}] {msg}' format_plugin_run = '' format_plugin_param = '' elif args.pretty == 'full': if not args.no_colors: format_host = { 'OK' : '%(gold)s{name:<34}%(default)s [%(green)s{status}%(default)s]' % COLORS, 'WARN' : '%(gold)s{name:<34}%(default)s [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : '%(gold)s{name:<34}%(default)s [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : '%(gold)s{name:<34}%(default)s [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin = { 'OK' : '- {name:<32} [%(green)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'WARN' : '- {name:<32} [%(yellow)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'ERROR': '- {name:<32} [%(red)s{lastResult[status]}%(default)s] (%(gray)s{lastResult[lastRun]}%(default)s)' % COLORS, 'UNKNOWN': '- {name:<32} [%(magenta)s{lastResult[status]}%(default)s]' % COLORS } format_plugin_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } format_plugin_component = { 'OK' : ' -- {name:<30} [%(green)s{status}%(default)s]' % COLORS, 'WARN' : ' -- {name:<30} [%(yellow)s{status}%(default)s]' % COLORS, 'ERROR' : ' -- {name:<30} [%(red)s{status}%(default)s]' % COLORS, 'UNKNOWN' : ' -- {name:<30} [%(magenta)s{status}%(default)s]' % COLORS, } format_plugin_component_msg = { 'info' : ' [%(blue)s{level}%(default)s] {msg}' % COLORS, 'warn' : ' [%(yellow)s{level}%(default)s] {msg}' % COLORS, 'error' : ' [%(red)s{level}%(default)s] {msg}' % COLORS, } else: format_host = '{name:<34} [{status}]' format_plugin = '- {name:<32} [{lastResult[status]}] ({lastResult[lastRun]})' format_plugin_msg = ' [{level}] {msg}' format_plugin_component = ' -- {name:<30} [{status}]' format_plugin_component_msg = ' [{level}] {msg}' format_plugin_run = ' Last run: {lastResult[lastRun]!s}\n Next run: {nextRun!s}' format_plugin_param = ' {key:<10} {value}' elif args.pretty in ['raw', 'json', 'tap']: # Raw and special outputs doesn't need formatting pass else: lg.error("Invalid pretty output %s" % args.pretty) sys.exit(1) # Plugins list and filter can't be set together if args.filter and args.plugins: lg.error("Plugins list and filters can't be used together") sys.exit(1) # Setup custom filters if args.category: args.filter.append('Category %s' % args.category) if args.component: args.filter.append('Component %s' % args.component) # Health checks and smoke tests together? Don't add filter if args.health or args.smoke: if args.health: args.filter.append('Type healthCheck') if args.smoke: args.filter.append('Type smokeTest') # Setup plugins filter filters = [] if args.filter: for f in args.filter: filter = {} try: filter = { 'key' : f.split(' ')[0], 'value': f.split(' ')[1] } except: lg.error("Invalid filter parameter format!") sys.exit(1) filters.append(filter) elif args.plugins: filters.append(args.plugins) # Setup state filters states = [] if args.filter_status: states = args.filter_status elif args.state_nook: states = ['ERROR', 'WARN', 'UNKNOWN'] else: if args.state_ok: states.append('OK') if args.state_error: states.append('ERROR') if args.state_warn: states.append('WARN') if args.state_unknown: states.append('UNKNOWN') # State list cannot be empty if not states: states = ['OK', 'ERROR', 'WARN', 'UNKNOWN'] # Add status filter filters.append(('status', states)) # Initialize Client client = Client(args.hosts) plugins = client.get_plugins(filters, filters_negative=args.exclude, exclude_plugins=args.exclude_plugins) # No plugins found if not plugins: lg.error("No plugins found") sys.exit(1) # List plugins only (parameter --force is ignored) if args.list: plugins_tuple = plugins.get_host_plugins() if plugins.count_hosts() > 1: # We have more hosts than 1, print structure like: # server1/httpd # server2/crond for host, plugin in plugins_tuple: print "%s/%s" % (host['name'], plugin['name']) else: # Print only plugin-by-line structure without hostname for host, plugin in plugins_tuple: print "%s" % plugin['name'] sys.exit(0) # Force plugins run # set progress=False if --no-progress parameter is set if args.force: plugins = client.force_run(plugins, progress=False if args.no_progress == True else True) # Print raw output if args.pretty == 'raw': from pprint import pprint pprint(plugins) sys.exit(0) elif args.pretty == 'json': # We need custom encoder to encode datetime objects class JSONEncoder(simplejson.JSONEncoder): """ JSON encoder that converts datetime.datetime object to isoformat string """ def default(self, obj): if isinstance(obj, datetime.datetime): return obj.isoformat() return simplejson.JSONEncoder.default(self, obj) print simplejson.dumps(plugins, cls=JSONEncoder) sys.exit(0) elif args.pretty == 'tap': dump = dump_tap(plugins) # Convert mixed string into ascii to workaround UnicodeEncodeError # shouldn't be needed in Python 3 print dump.encode('ascii', 'ignore') sys.exit(0) # Print result output = [] hosts_printed = [] for host, plugin in plugins.get_host_plugins(): # Print host if not already printed if host['name'] not in hosts_printed: # Add empty line if any previous host if hosts_printed: output.append(" ") if isinstance(format_host, dict): output.append(format_host[host['status']].format(**host)) else: output.append(format_host.format(**host)) hosts_printed.append(host['name']) # Print plugin if not isinstance(plugin, dict): # Not a plugin continue if isinstance(format_plugin, basestring): output.append(format_plugin.format(**plugin)) else: output.append(format_plugin[plugin['lastResult']['status']].format(**plugin)) # Print last and next plugin run output.append(format_plugin_run.format(**plugin)) # Print last and next plugin run for key, value in plugin['parameters'].iteritems(): output.append(format_plugin_param.format(key=key, value=value)) # Print plugin messages if plugin['lastResult']['messages']: # For each message level for level, message in plugin['lastResult']['messages'].iteritems(): # For each message for msg in message: if isinstance(format_plugin_msg, basestring): output.append(format_plugin_msg.format(level=level, msg=msg.encode('utf8'))) else: output.append(format_plugin_msg[level].format(level=level, msg=msg.encode('utf8'))) # Print component result if plugin['lastResult']['componentResults']: for component in plugin['lastResult']['componentResults']: component = component['componentResult'] if isinstance(format_plugin_component, basestring): output.append(format_plugin_component.format(**component)) else: output.append(format_plugin_component[component['status']].format(**component)) # Print component messages if component['messages']: # For each message level for level, message in component['messages'].iteritems(): # For each message for msg in message: if isinstance(format_plugin_component_msg, basestring): output.append(format_plugin_component_msg.format(level=level, msg=msg.encode('utf8'))) else: output.append(format_plugin_component_msg[level].format(level=level, msg=msg.encode('utf8'))) for line in output: if line: print line
def main(): client = Client(['localhost']) plugins = None if args.plugin: if args.category or args.component or args.health: lg.warn("Plugins specified by name, ignoring --category, --component and --health") plugins = client.get_plugins([args.plugin]) elif args.category or args.component or args.health: filter = [] if args.category: filter.append({'key': 'Category', 'value': args.category}) if args.component: filter.append({'key': 'Component', 'value': args.component}) if args.health: filter.append({'key': 'Type', 'value': 'healthCheck'}) plugins = client.get_plugins(filter) else: nagios.exit_unknown("invalid startup configuration - neither plugin nor --category nor --component " "nor --health specified") # No plugin found if not plugins: if args.plugin: message = "plugin %s not found" % args.plugin else: message = "no plugin found by category %s and component %s, health: %s" % \ (args.category, args.component, args.health) nagios.exit_unknown(message) if args.force: plugins = client.force_run(plugins, progress=False) status_methods_pairs = [(ERROR, nagios.exit_critical), (UNKNOWN, nagios.exit_unknown), (WARN, nagios.exit_warning), (OK, nagios.exit_ok)] # Manage plugin result. We can't return much data to Nagios, so just say if it's alright or not results = dict((s, []) for s, _ in status_methods_pairs) for plugin in plugins.values()[0]['plugins'].itervalues(): plugin_name = plugin['name'] if not plugin['lastResult']: results[UNKNOWN].append({'name': plugin_name, 'message': "plugin has no last result"}) else: last_status = plugin['lastResult']['status'] if last_status in [ERROR, WARN, OK]: try: results[last_status].append({'name': plugin_name, 'message': plugin['lastResult']['messages'][last_status.lower()][0]}) except (KeyError, IndexError, TypeError): if last_status == OK: results[last_status].append( {'name': plugin_name, 'message': "smoke test %s succeeded at %s" % (plugin['name'], plugin['lastResult']['lastRun'])}) else: results[last_status].append({'name': plugin_name, 'message': parse_issue(plugin)}) else: results[UNKNOWN].append({'name': plugin_name, 'message': "unknown status %s at %s" % (plugin['lastResult']['status'], plugin['lastResult']['lastRun'])}) for status, exit_method in status_methods_pairs: if results[status]: if len(plugins.values()[0]['plugins']) == 1: # if only one plugin has been executed, do not print summary exit_method(results[status][0]['message']) else: summary = ', '.join(["%s: %s" % (s, len(results[s])) for s, _ in status_methods_pairs if results[s]]) messages = ['\n'.join(["%s - %s - %s" % (s, item['name'], item['message']) for item in list]) for s, list in results.iteritems() if list] exit_method("%s\n%s" % (summary, '\n'.join(messages)))