Monitoring PVC-PV-RBD and mapping them
The script allows to monitor if PVC has associated PV and RBD associated with PV. usage: 001-pvc_rbd_monitoring.py [-h] [--rbd] [--pvc] [--all] [--pv] [--bin] [--config] [--debug | --silent] optional arguments: -h, --help show this help message and exit --debug, -d enable debugging (default: False) --silent, -s don't log into console (default: False) monitoring settigns: --rbd, -r check rbd (default: False) --pvc, -p check permanent volume claim (default: False) --all, -a all checks (default: False) --pv check permanent volumes (default: False) --bin, -e path to kubecl binary (default: None) --config, -c path to kubecl config (default: None) Change-Id: If88979d645c543ff778201c597f898b7c7aa0388
This commit is contained in:
parent
064185e1af
commit
8a1fdb960c
290
tools/fixes/pvc_pv_rbd_monitoring.py
Normal file
290
tools/fixes/pvc_pv_rbd_monitoring.py
Normal file
@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
import json
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
|
||||
|
||||
# need to export path to configuration file. should work faster
|
||||
if os.environ["KUBECONFIG"] !="":
|
||||
CONFIG = "KUBECONFIG={}".format(os.environ["KUBECONFIG"])
|
||||
else:
|
||||
CONFIG = "KUBECONFIG=/etc/kubernetes/admin/kubeconfig.yaml"
|
||||
if os.environ["KUBECTL"] != "":
|
||||
KUBECTL = os.environ["KUBECTL"]
|
||||
else:
|
||||
KUBECTL = "/usr/local/bin/kubectl"
|
||||
|
||||
OPTIONS = {
|
||||
'read': "-o json",
|
||||
'ns': "-n",
|
||||
'exec': ""
|
||||
}
|
||||
|
||||
logger = logging.getLogger(os.path.splitext(os.path.basename(sys.argv[0]))[0])
|
||||
|
||||
kubectl = "{config} {kubectl} {options} {namespace}".format(config=CONFIG,
|
||||
kubectl=KUBECTL,
|
||||
namespace=OPTIONS["ns"],
|
||||
options=OPTIONS["read"])
|
||||
|
||||
kubectl_exec = "{config} {kubectl} {options} {namespace}".format(config=CONFIG,
|
||||
kubectl=KUBECTL,
|
||||
namespace=OPTIONS["ns"],
|
||||
options=OPTIONS["exec"])
|
||||
|
||||
|
||||
class CustomFormatter(argparse.RawDescriptionHelpFormatter,
|
||||
argparse.ArgumentDefaultsHelpFormatter):
|
||||
pass
|
||||
|
||||
|
||||
def parse_args(args=sys.argv[1:]):
|
||||
""" parse arguments of script """
|
||||
|
||||
logger.debug("Parsing arguments")
|
||||
parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__,
|
||||
formatter_class=CustomFormatter)
|
||||
g = parser.add_argument_group("monitoring settigns")
|
||||
g.add_argument("--rbd", "-r", action="store_true",
|
||||
default=False, help="check rbd")
|
||||
g.add_argument("--pvc", "-p", action="store_true",
|
||||
default=False, help="check permanent volume claim")
|
||||
g.add_argument("--all", "-a", action="store_true",
|
||||
default=False, help="all checks")
|
||||
g.add_argument("--pv", action="store_true",
|
||||
default=False, help="check permanent volumes")
|
||||
|
||||
# configuration options
|
||||
g.add_argument("--bin", "-e", action="store_const",
|
||||
const=KUBECTL,
|
||||
help="path to kubecl binary")
|
||||
g.add_argument("--config", "-c", action="store_const",
|
||||
const=CONFIG,
|
||||
help="path to kubecl config")
|
||||
|
||||
# debug options
|
||||
g = parser.add_mutually_exclusive_group()
|
||||
g.add_argument("--debug", "-d", action="store_true",
|
||||
default=False, help="enable debugging")
|
||||
g.add_argument("--silent", "-s", action="store_true",
|
||||
default=False, help="don't log into console")
|
||||
return parser.parse_args(args)
|
||||
|
||||
|
||||
def setup_logging(options):
|
||||
""" configure logging """
|
||||
|
||||
logger.debug("Configuring logging")
|
||||
root = logging.getLogger("")
|
||||
root.setLevel(logging.WARNING)
|
||||
logger.setLevel(options.debug and logging.DEBUG or logging.INFO)
|
||||
if not options.silent:
|
||||
ch = logging.StreamHandler()
|
||||
ch.setFormatter(logging.Formatter("%(levelname)s [%(name)s] %(message)s"))
|
||||
root.addHandler(ch)
|
||||
|
||||
|
||||
def get_podname(label, namespace):
|
||||
""" return list of pods in provided namespaces with label """
|
||||
|
||||
logger.debug("Getting pod names with labels {label} in namespcae {namespace}".format(label=label,
|
||||
namespace=namespace))
|
||||
command = "{command} {namespace} get pods -l {label}".format(command=kubectl,
|
||||
namespace=namespace,
|
||||
label=label)
|
||||
logger.debug(command)
|
||||
try:
|
||||
output = run_command(command)
|
||||
except Exception as e:
|
||||
logger.error("Getting pod names for labels {label} in namespace {namespace}".format(label=label,
|
||||
namespace=namespace))
|
||||
sys.exit(1)
|
||||
|
||||
podnames = []
|
||||
try:
|
||||
out = json.loads(output)
|
||||
for item in out["items"]:
|
||||
if item['kind'] == "Pod":
|
||||
podnames.append(item['metadata']['name'])
|
||||
except Exception as e:
|
||||
sys.exit(1)
|
||||
return podnames
|
||||
|
||||
|
||||
def run_command(command):
|
||||
""" run command in linux shell and return a result """
|
||||
|
||||
try:
|
||||
result = subprocess.check_output(command,
|
||||
shell=True).strip().decode('utf-8')
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
sys.exit(1)
|
||||
return result
|
||||
|
||||
|
||||
def check_rbd_status(namespace, rbd):
|
||||
""" return status or rbd in json format """
|
||||
|
||||
ceph_mon = get_podname("application=ceph,component=mon", namespace)[0]
|
||||
command = "{command} {namespace} exec -it {pod} -- rbd status --format json {rbd}".format(command=kubectl_exec,
|
||||
namespace=namespace,
|
||||
rbd=rbd, pod=ceph_mon)
|
||||
out = run_command(command)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
except Exception as e:
|
||||
output = "{{'rbd': {}, 'status': {} }}".format(rbd, e)
|
||||
return output
|
||||
|
||||
|
||||
def get_pvc(namespace):
|
||||
""" return list of permanent volume claim in specific namespace """
|
||||
|
||||
command = "{command} {namespace} get pvc".format(command=kubectl,
|
||||
namespace=namespace)
|
||||
out = run_command(command)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
except Exception as e:
|
||||
# output = {'namespace': namespace, 'status': e}
|
||||
output = []
|
||||
return output
|
||||
|
||||
|
||||
def get_pv(persistentvolume, namespace):
|
||||
""" return list of persistent volumes in specific namespace """
|
||||
|
||||
command = "{command} {namespace} get pv {pv}".format(command=kubectl,
|
||||
namespace=namespace,
|
||||
pv=persistentvolume)
|
||||
out = run_command(command)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
except Exception as e:
|
||||
output = {'persistentvolume': namespace, 'status': e}
|
||||
return output
|
||||
|
||||
|
||||
def get_namespaces():
|
||||
""" return list of namespaces """
|
||||
|
||||
command = "{command} {namespace} get ns -o json".format(command=kubectl_exec,
|
||||
namespace="ceph")
|
||||
out = run_command(command)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
except Exception as e:
|
||||
output = {"Error": e}
|
||||
return output
|
||||
|
||||
|
||||
def get_rbd_list(namespace):
|
||||
""" return list of rbd in json format """
|
||||
|
||||
ceph_mon = get_podname("application=ceph,component=mon", namespace)[0]
|
||||
command = "{command} {namespace} exec -it {pod} -- rbd ls --format json".format(command=kubectl_exec,
|
||||
namespace=namespace,
|
||||
pod=ceph_mon)
|
||||
out = run_command(command)
|
||||
logger.debug(out)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
except Exception as e:
|
||||
output = "{{'namaspace': {}, 'status': {} }}".format(namespace, e)
|
||||
logger.error("parse json rbd list output: {}".format(e))
|
||||
return output
|
||||
|
||||
|
||||
def monitoring_pvc():
|
||||
logger.info("PVCs aren't associated with RBD")
|
||||
rbds = get_rbd_list("ceph")
|
||||
logger.info("Gettign list of namespaces")
|
||||
namespaces = get_namespaces()
|
||||
for namespace in namespaces['items']:
|
||||
ns = namespace['metadata']['name']
|
||||
logger.info("Checking namespace: {}".format(ns))
|
||||
pvc = get_pvc(ns)
|
||||
for pv in pvc['items']:
|
||||
rbd = get_pv(pv['spec']['volumeName'], ns)
|
||||
rbd = rbd['spec']['rbd']['image']
|
||||
if rbd not in rbds:
|
||||
print ("pvc_doesnot_have_rbd:{{namespace={},name={}}} 0".format(ns, pv['metadata']['name']))
|
||||
|
||||
|
||||
def monitoring_rbd():
|
||||
logger.info("RBD volumes aren't associated with PVC")
|
||||
r = get_rbd_list("ceph")
|
||||
rbds = []
|
||||
namespaces = get_namespaces()
|
||||
for namespace in namespaces['items']:
|
||||
ns = namespace['metadata']['name']
|
||||
pvc = get_pvc(ns)
|
||||
for pv in pvc['items']:
|
||||
rbd = get_pv(pv['spec']['volumeName'], ns)
|
||||
rbd = rbd['spec']['rbd']['image']
|
||||
rbds.append(rbd)
|
||||
logger.info(rbd)
|
||||
for i in r:
|
||||
if i not in rbds:
|
||||
logger.debug(i)
|
||||
print ("rbd_doesnot_have_pvc:{{name={}}} {}".format(i, len(check_rbd_status("ceph", i)['watchers'])))
|
||||
|
||||
|
||||
def monitoring_pv():
|
||||
logger.info("PVs aren't associated with PVC ")
|
||||
command = "{config} {kubectl} get pv -o json".format(config=CONFIG, kubectl=KUBECTL)
|
||||
logger.debug(command)
|
||||
out = run_command(command)
|
||||
logger.debug(out)
|
||||
try:
|
||||
output = json.loads(out)
|
||||
for pv in output['items']:
|
||||
if pv['status']['phase'] == "Released":
|
||||
print ("pv_released:{{name={},status={}}} 0".format(pv['metadata']['name'], pv['status']['phase']))
|
||||
except Exception as e:
|
||||
logger.error("gettign rbd list: {}".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def monitoring():
|
||||
monitoring_rbd()
|
||||
monitoring_pvc()
|
||||
monitoring_pv()
|
||||
|
||||
|
||||
def main():
|
||||
# nagios monitoring
|
||||
# 0 - Service is OK.
|
||||
# 1 - Service has a WARNING.
|
||||
# 2 - Service is in a CRITICAL status.
|
||||
# 3 - Service status is UNKNOWN
|
||||
|
||||
# promotheus text file
|
||||
options = parse_args()
|
||||
setup_logging(options)
|
||||
|
||||
|
||||
if options.all:
|
||||
logger.info("all")
|
||||
monitoring()
|
||||
if options.rbd:
|
||||
logger.info("rbd")
|
||||
monitoring_rbd()
|
||||
if options.pvc:
|
||||
logger.info("pvc")
|
||||
monitoring_pvc()
|
||||
if options.pv:
|
||||
logger.info("pv")
|
||||
monitoring_pv()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user