#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright (c) 2018 SWITCH http://www.switch.ch # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import argparse import os import subprocess import sys import json __version__ = '1.0.0' # default ceph values CEPH_EXEC = '/usr/bin/ceph' CEPH_COMMAND = 'mgr dump -f json' CEPH_MGR_DUMP_EXAMPLE = ''' $ ceph --version ceph version 12.2.7 (3ec878d1e53e1aeb47a9f619c49d9e7c0aa384d5) luminous (stable) $ ceph mgr dump -f json|jq . { "epoch": 165, "active_gid": 248001409, "active_name": "zhdk0013", "active_addr": "10.10.10.9:6800/810408", "available": true, "standbys": [ { "gid": 247991934, "name": "zhdk0009", "available_modules": [ "balancer", "dashboard", "influx", "localpool", "prometheus", "restful", "selftest", "status", "zabbix" ] }, { "gid": 248011196, "name": "zhdk0025", "available_modules": [ "balancer", "dashboard", "influx", "localpool", "prometheus", "restful", "selftest", "status", "zabbix" ] } ], "modules": [ "balancer", "restful", "status" ], "available_modules": [ "balancer", "dashboard", "influx", "localpool", "prometheus", "restful", "selftest", "status", "zabbix" ], "services": {} } ''' # nagios exit code STATUS_OK = 0 STATUS_WARNING = 1 STATUS_ERROR = 2 STATUS_UNKNOWN = 3 def main(): # parse args parser = argparse.ArgumentParser(description="'ceph mgr dump' nagios plugin.") parser.add_argument('-e', '--exe', help='ceph executable [%s]' % CEPH_EXEC) parser.add_argument('-c', '--conf', help='alternative ceph conf file') parser.add_argument('-m', '--monaddress', help='ceph monitor to use for queries (address[:port])') parser.add_argument('-i', '--id', help='ceph client id') parser.add_argument('-n', '--name', help='ceph client name') parser.add_argument('-k', '--keyring', help='ceph client keyring file') parser.add_argument('-V', '--version', help='show version and exit', action='store_true') args = parser.parse_args() if args.version: print("version {}".format(__version__)) return STATUS_OK # validate args ceph_exec = args.exe if args.exe else CEPH_EXEC if not os.path.exists(ceph_exec): print("MGR ERROR: ceph executable '{}' doesn't exist".format(ceph_exec)) return STATUS_UNKNOWN if args.conf and not os.path.exists(args.conf): print("MGR ERROR: ceph conf file '{}' doesn't exist".format(args.conf)) return STATUS_UNKNOWN if args.keyring and not os.path.exists(args.keyring): print("MGR ERROR: keyring file '{}' doesn't exist".format(args.keyring)) return STATUS_UNKNOWN # build command ceph_cmd = [ceph_exec] if args.monaddress: ceph_cmd.append('-m') ceph_cmd.append(args.monaddress) if args.conf: ceph_cmd.append('-c') ceph_cmd.append(args.conf) if args.id: ceph_cmd.append('--id') ceph_cmd.append(args.id) if args.name: ceph_cmd.append('--name') ceph_cmd.append(args.name) if args.keyring: ceph_cmd.append('--keyring') ceph_cmd.append(args.keyring) ceph_cmd.extend(CEPH_COMMAND.split(' ')) # exec command p = subprocess.Popen(ceph_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = p.communicate() if p.returncode != 0 or not output: print("MGR ERROR: {}".format(err)) return STATUS_UNKNOWN # load json output and parse mgr_dump = None try: mgr_dump = json.loads(output) except Exception as e: print("MGR ERROR: could not parse '{}' output: {}: {}".format(ceph_cmd, output, e)) return STATUS_UNKNOWN # check active if 'active_name' not in mgr_dump: print("MGR CRITICAL: not active mgr found") print("JSON: {}".format(json.dumps(mgr_dump))) return STATUS_ERROR active_mgr_name = mgr_dump['active_name'] # check standby standby_mgr_names = [] for standby_mgr in mgr_dump['standbys']: standby_mgr_names.append(standby_mgr['name']) if len(standby_mgr_names) <= 0: print("MGR WARN: active: {} but no standbys".format(active_mgr_name)) return STATUS_WARNING else: print("MGR OK: active: {}, standbys: {}".format(active_mgr_name, ", ".join(standby_mgr_names))) return STATUS_OK # main if __name__ == "__main__": sys.exit(main())