|
| 1 | +#!/usr/bin/env ruby |
| 2 | +# encoding: UTF-8 |
| 3 | +# |
| 4 | +# check-zookeeper-mode |
| 5 | +# |
| 6 | +# DESCRIPTION: |
| 7 | +# Check if Zookeeper node is in expected mode. |
| 8 | +# |
| 9 | +# 'mode' is ZooKeeper's mode which can be standalone or in a cluster. |
| 10 | +# In cluster mode a Zookeeper node can be either leader or follower. |
| 11 | +# We use stat command to get the mode and check if zookeeper node is a |
| 12 | +# standalone or leader or follower. |
| 13 | +# |
| 14 | +# PLATFORMS: |
| 15 | +# All |
| 16 | +# |
| 17 | +# DEPENDENCIES: |
| 18 | +# gem: sensu-plugin |
| 19 | +# |
| 20 | +# USAGE: |
| 21 | +# Check if a node has Zookeeper running and responds with imok. |
| 22 | +# ./check-zookeeeper-mode.rb -m 'leader follower' |
| 23 | +# ./check-zookeeeper-mode.rb -s localhost -p 2181 -m 'leader follower' |
| 24 | +# ./check-zookeeeper-mode.rb --server localhost --port 2181 --mode 'leader follower' |
| 25 | +# |
| 26 | + |
| 27 | +require 'sensu-plugin/check/cli' |
| 28 | +require 'socket' |
| 29 | + |
| 30 | +class CheckZookeeperMode < Sensu::Plugin::Check::CLI |
| 31 | + option :server, |
| 32 | + description: 'Zookeeper hostname to connect to.', |
| 33 | + short: '-s HOSTNAME', |
| 34 | + long: '--server HOSTNAME', |
| 35 | + default: 'localhost' |
| 36 | + |
| 37 | + option :port, |
| 38 | + description: 'Zookeeper port to connect to.', |
| 39 | + short: '-p PORT', |
| 40 | + long: '--port PORT', |
| 41 | + default: 2181 |
| 42 | + |
| 43 | + option :timeout, |
| 44 | + description: 'How long to wait for a reply in seconds.', |
| 45 | + short: '-t SECS', |
| 46 | + long: '--timeout SECS', |
| 47 | + proc: proc(&:to_i), |
| 48 | + default: 5 |
| 49 | + |
| 50 | + option :mode, |
| 51 | + description: 'Space separated expected modes.', |
| 52 | + short: '-m MODE', |
| 53 | + long: '--mode MODE', |
| 54 | + required: true |
| 55 | + |
| 56 | + def zk_command(four_letter_word) |
| 57 | + Socket.tcp(config[:server], config[:port]) do |sock| |
| 58 | + sock.print "#{four_letter_word}\r\n" |
| 59 | + sock.close_write |
| 60 | + sock.read |
| 61 | + end |
| 62 | + end |
| 63 | + |
| 64 | + def run |
| 65 | + response = zk_command(:stat) |
| 66 | + mode = get_mode(response) |
| 67 | + expected_modes = config[:mode].split |
| 68 | + if expected_modes.include?(mode) |
| 69 | + ok(mode) |
| 70 | + else |
| 71 | + critical("Zookeeper mode is #{mode} and it does not match #{expected_modes.join(', ')}") |
| 72 | + end |
| 73 | + end |
| 74 | + |
| 75 | + private |
| 76 | + |
| 77 | + def get_mode(response) |
| 78 | + response.each_line do |line| |
| 79 | + line = line.chomp |
| 80 | + k, v = line.split(': ') |
| 81 | + return v if k == 'Mode' |
| 82 | + end |
| 83 | + end |
| 84 | +end |
0 commit comments