164 lines
4.5 KiB
Python
Executable File
164 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (c) 2013 Catalyst IT http://www.catalyst.net.nz
|
|
# Copyright (c) 2015 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 socket
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
import json
|
|
|
|
__version__ = '1.5.0'
|
|
|
|
# default ceph values
|
|
CEPH_EXEC = '/usr/bin/ceph'
|
|
CEPH_COMMAND = 'quorum_status'
|
|
|
|
# nagios exit code
|
|
STATUS_OK = 0
|
|
STATUS_WARNING = 1
|
|
STATUS_ERROR = 2
|
|
STATUS_UNKNOWN = 3
|
|
|
|
##
|
|
# ceph quorum_status output example
|
|
##
|
|
ceph_quorum_status_output_example = '''{
|
|
"quorum_leader_name" : "s0001",
|
|
"monmap" : {
|
|
"mons" : [
|
|
{
|
|
"name" : "s0001",
|
|
"addr" : "[2001:620:5ca1:8000::1001]:6789/0",
|
|
"rank" : 0
|
|
},
|
|
{
|
|
"name" : "s0003",
|
|
"addr" : "[2001:620:5ca1:8000::1003]:6789/0",
|
|
"rank" : 1
|
|
}
|
|
],
|
|
"created" : "2014-12-15 08:28:35.153650",
|
|
"epoch" : 2,
|
|
"modified" : "2014-12-15 08:28:40.371878",
|
|
"fsid" : "22348d2b-b69d-46cc-9a79-ca93cd6bae84"
|
|
},
|
|
"quorum_names" : [
|
|
"s0001",
|
|
"s0003"
|
|
],
|
|
"quorum" : [
|
|
0,
|
|
1
|
|
],
|
|
"election_epoch" : 24
|
|
}'''
|
|
|
|
def main():
|
|
|
|
# parse args
|
|
parser = argparse.ArgumentParser(description="'ceph quorum_status' 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('-k','--keyring', help='ceph client keyring file')
|
|
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
|
parser.add_argument('-I','--monid', help='mon ID to be checked for availability')
|
|
args = parser.parse_args()
|
|
|
|
if args.version:
|
|
print('version %s' % __version__)
|
|
return STATUS_OK
|
|
|
|
# validate args
|
|
ceph_exec = args.exe if args.exe else CEPH_EXEC
|
|
if not os.path.exists(ceph_exec):
|
|
print("MON ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
|
return STATUS_UNKNOWN
|
|
|
|
if args.conf and not os.path.exists(args.conf):
|
|
print("MON ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
|
return STATUS_UNKNOWN
|
|
|
|
if args.keyring and not os.path.exists(args.keyring):
|
|
print("MON ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
|
return STATUS_UNKNOWN
|
|
|
|
if not args.monid:
|
|
print("MON ERROR: no MON ID given, use -I/--monid parameter")
|
|
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.keyring:
|
|
ceph_cmd.append('--keyring')
|
|
ceph_cmd.append(args.keyring)
|
|
ceph_cmd.append(CEPH_COMMAND)
|
|
|
|
# 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("MON ERROR: %s" % err)
|
|
return STATUS_ERROR
|
|
|
|
# load json output and parse
|
|
quorum_status = False
|
|
try:
|
|
quorum_status = json.loads(output)
|
|
except Exception as e:
|
|
print("MON ERROR: could not parse '%s' output: %s: %s" % (CEPH_COMMAND,output,e))
|
|
return STATUS_UNKNOWN
|
|
|
|
#print "XXX: quorum_status['quorum_names']:", quorum_status['quorum_names']
|
|
|
|
# do our checks
|
|
is_monitor = False
|
|
for mon in quorum_status['monmap']['mons']:
|
|
if mon['name'] == args.monid:
|
|
is_monitor = True
|
|
if not is_monitor:
|
|
print("MON WARN: mon '%s' is not in monmap: %s" % (args.monid,quorum_status['monmap']['mons']))
|
|
return STATUS_WARNING
|
|
|
|
in_quorum = args.monid in quorum_status['quorum_names']
|
|
if in_quorum:
|
|
print("MON OK")
|
|
return STATUS_OK
|
|
else:
|
|
print("MON WARN: no MON '%s' found in quorum" % args.monid)
|
|
return STATUS_WARNING
|
|
|
|
# main
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|