ruby-nagios 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1 +1,4 @@
1
1
  pkg
2
+ doc
3
+ .yardoc
4
+ .DS_Store
data/Rakefile CHANGED
@@ -1,2 +1,20 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
+
4
+ namespace :spec do
5
+
6
+ desc "Run production configuration test"
7
+ task :config do
8
+ ENV['RSPEC_ENV'] = 'production'
9
+ sh %{rspec -f d --color --fail-fast spec/00_configuration_spec.rb}
10
+ end
11
+
12
+ namespace :test do
13
+
14
+ desc "Run configuration test in `test` environment"
15
+ task :config do
16
+ ENV['RSPEC_ENV'] = 'test'
17
+ sh %{rspec -f d --color spec/00_configuration_spec.rb}
18
+ end
19
+ end
20
+ end
data/bin/check_check CHANGED
@@ -23,12 +23,12 @@ class Nagios::Status::Model
23
23
 
24
24
  def initialize(path)
25
25
  @path = path
26
- @status = Nagios::Status.new
26
+ @status = Nagios::Status.new @path
27
27
  update
28
28
  end # def initialize
29
29
 
30
30
  def update
31
- @status.parsestatus(@path)
31
+ @status.parsestatus
32
32
  end # def update
33
33
 
34
34
  def services(service_pattern=nil, host_pattern=nil)
@@ -160,6 +160,14 @@ def main(args)
160
160
  end # if results[state]
161
161
  end # for each non-OK state
162
162
 
163
+ # If everything is OK, still print detailed output for confirmation
164
+ if total_results == 0 and results["OK"].size > 0
165
+ puts "OK Services:"
166
+ results["OK"].sort { |a,b| a["host_name"] <=> b["host_name"] }.each do |service|
167
+ puts " #{service["host_name"]} => #{service["service_description"]}"
168
+ end
169
+ end
170
+
163
171
  exitcode = 0
164
172
 
165
173
  if settings.down_min_percent
data/bin/nagsrv CHANGED
@@ -77,7 +77,7 @@ OptionParser.new do |opts|
77
77
  end
78
78
 
79
79
  opts.on("--list-services", "List services that match certain criteria") do
80
- listhosts = true
80
+ listservices = true
81
81
  end
82
82
 
83
83
  opts.separator ""
@@ -128,9 +128,9 @@ end.parse!
128
128
 
129
129
  abort "Cannot find #{statusfile}" unless File.exist?(statusfile)
130
130
 
131
- nagios = Nagios::Status.new
131
+ nagios = Nagios::Status.new statusfile
132
132
 
133
- nagios.parsestatus(statusfile)
133
+ nagios.parsestatus
134
134
 
135
135
 
136
136
  # We want hosts so abuse the action field to print just the hostname
@@ -141,6 +141,10 @@ if listhosts
141
141
  forhost = "/." if forhost.size == 0
142
142
  end
143
143
 
144
+ if listservices && action == nil
145
+ action = "${service}"
146
+ end
147
+
144
148
  options = {:forhost => forhost, :notifyenabled => notify, :action => action, :withservice => withservice}
145
149
  services = nagios.find_services(options)
146
150
 
data/lib/nagios/config.rb CHANGED
@@ -2,10 +2,11 @@ module Nagios
2
2
 
3
3
  =begin rdoc
4
4
 
5
- Configuration parser for Nagios. Constructor parses Nagios' main
6
- config file and returns an object: each configuration option's value
7
- assigned to an instance variable and attribute reader method is
8
- created.
5
+ Parser of the main Nagios configuration file -- nagios.cfg.
6
+
7
+ Constructor parses Nagios' main config file and returns an object:
8
+ each configuration option's value assigned to an instance variable and
9
+ attribute reader method is created.
9
10
 
10
11
  Can be used as:
11
12
 
@@ -18,43 +19,82 @@ Can be used as:
18
19
  nagios.status_file
19
20
  => "/var/cache/nagios3/status.dat"
20
21
 
22
+ = Configuration of the module
23
+
24
+ Default search directory and file pattern (Dir.glob) is defined by
25
+ Nagios::DEFAULT[:nagios_cfg_glob] constant. It is set in
26
+ +config/default.rb+ file.
27
+
28
+ @note If you have more than one /etc/nagios* directories then only
29
+ first one will be used. For example, Debian can have both Nagios 2 and
30
+ 3 installed. In the latter case configuration file is
31
+ +/etc/nagios3/nagios.cfg+.
32
+
21
33
 
22
34
  =end
23
35
  class Config
24
36
 
25
- DEFAULT_CONFIG = "/etc/nagios*/nagios.cfg"
26
-
27
- # Read and parse configuration file.
28
- #
37
+ ##
38
+ # Initialize configuration file path. Check existence and
39
+ # readability of the file, raise exception if not.
40
+ #
29
41
  # @param [String] config_file PATH to the configuration file. If
30
42
  # PATH is not provided method will look for configuration file
31
- # +nagios.cfg+ in +/etc/nagios*+ directory.
32
- # @note If you have more than one /etc/nagios* directories then
33
- # only first one will be used. For example, Debian can have
34
- # both Nagios 2 and 3 installed. In the latter case
35
- # configuration file is +/etc/nagios3/nagios.cfg+.
36
- # @author Dmytro Kovalov, dmytro.kovalov@gmail.com
43
+ # +nagios.cfg+ in directory, defined by
44
+ # Nagios::DEFAULT[:nagios_cfg_glob] constant ( ususally
45
+ # /etc/nagios*/nagios.cfg);
46
+ #
37
47
  def initialize config_file=nil
38
- @config = config_file || Dir.glob(DEFAULT_CONFIG).first
39
-
40
- raise "No configuration file option and no files in #{DEFAULT_CONFIG} " unless @config
48
+
49
+ @config = config_file || Dir.glob( Nagios::DEFAULT[:nagios_cfg_glob] ).first
50
+ @path = @config
51
+
52
+ @configuration ||= {}
53
+ raise "No configuration file option and no files in #{ DEFAULT[:nagios_cfg_glob] } " unless @config
41
54
  raise "Configuration file #{@config} does not exist" unless File.exist? @config
42
55
  raise "Configuration file #{@config} is not readable" unless File.readable? @config
43
56
 
44
- File.readlines(@config).map{ |l| l.sub(/#.*$/,'')}.delete_if { |l| l=~ /^$/}.each do |l|
45
- key,val = l.strip.split('=',2)
46
- raise "Incorrect configuration line #{l}" unless key && val
57
+ end
58
+
59
+ # Hash holding all the configuration after parsing. Additionally
60
+ # for every key in the configuration Hash method is created with
61
+ # the same name, which returns the value.
62
+ attr_accessor :configuration
63
+
64
+ # Path to main configuration file nagios.cfg
65
+
66
+ attr_accessor :path
67
+
68
+ ##
69
+ # Read and parse main Nagios configuration file +nagios.cfg+
70
+ #
71
+ #
72
+ # @author Dmytro Kovalov, dmytro.kovalov@gmail.com
73
+ def parse
74
+ idx=0
75
+ File.readlines(@config).map{ |l| l.sub(/\s*#.*$/,'')}.delete_if { |l| l=~ /^\s*$/}.each do |l|
76
+ idx += 1
77
+ key,val = l.chomp.strip.split(/\s*=\s*/,2)
78
+ raise "Incorrect configuration line ##{idx}: '#{l}'" unless key && val
47
79
 
48
80
  case key
49
- when /cfg_(file|dir)/ # There could be multiple entries for cfg_dir/file
81
+ # There could be multiple entries for cfg_dir/file, so these
82
+ # are Arrays.
83
+ when /cfg_(file|dir)/
84
+ @configuration[key] ||= []
85
+ @configuration[key] << val
50
86
  instance_variable_set("@#{key}", (instance_variable_get("@#{key}") || []) << val )
51
87
  else
88
+
89
+ @configuration[key] = val
52
90
  instance_variable_set("@#{key}", val)
53
91
  instance_eval val =~ /^[\d\.-]+/ ?
54
92
  "def #{key}; return #{val}; end" :
55
93
  "def #{key}; return %Q{#{val}}; end"
56
94
  end
57
95
  end
96
+
97
+ self
58
98
  end
59
99
 
60
100
  # Special case for cfg_file and cfg_dir: they are Arrays
@@ -0,0 +1,186 @@
1
+ module Nagios
2
+ class ExternalCommands
3
+ # External commands list in nagios and format to send this to
4
+ # Nagios. Keys of the Hash are names of commands, values are
5
+ # Array's of Nagios variables to be sent. Arrays are converted to
6
+ # ERB templates before printing, command name and all variables
7
+ # joined together by semicolons.
8
+ #
9
+ # Each variable must be defined as attr_accessor, these variables
10
+ # are used in ERB binding.
11
+ #
12
+ # List of all available nagios external commands, formats and
13
+ # descriptions can be obtained from
14
+ # http://www.nagios.org/developerinfo/externalcommands As of the
15
+ # time of writing this list is 157 commands for Nagios 3.x.
16
+ #
17
+ # == Example
18
+ #
19
+ # PROCESS_SERVICE_CHECK_RESULT: %w{host_name service_description return_code plugin_output}
20
+ #
21
+ # converted to template on print:
22
+ #
23
+ # [timestamp] PROCESS_SERVICE_CHECK_RESULT;<%= host_name %>;<%= service_description %>;<%= return_code %>;<%= plugin_output %>\n
24
+ #
25
+ ACTIONS = {
26
+ ACKNOWLEDGE_HOST_PROBLEM: %w{host_name sticky notify persistent author comment},
27
+ ACKNOWLEDGE_SVC_PROBLEM: %w{host_name service_description sticky notify persistent author comment},
28
+ ADD_HOST_COMMENT: %w{host_name persistent author comment},
29
+ ADD_SVC_COMMENT: %w{host_name service_description persistent author comment},
30
+ CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD: %w{contact_name notification_timeperiod},
31
+ CHANGE_CONTACT_MODATTR: %w{contact_name value},
32
+ CHANGE_CONTACT_MODHATTR: %w{contact_name value},
33
+ CHANGE_CONTACT_MODSATTR: %w{contact_name value},
34
+ CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD: %w{contact_name notification_timeperiod},
35
+ CHANGE_CUSTOM_CONTACT_VAR: %w{contact_name varname varvalue},
36
+ CHANGE_CUSTOM_HOST_VAR: %w{host_name varname varvalue},
37
+ CHANGE_CUSTOM_SVC_VAR: %w{host_name service_description varname varvalue},
38
+ CHANGE_GLOBAL_HOST_EVENT_HANDLER: %w{event_handler_command},
39
+ CHANGE_GLOBAL_SVC_EVENT_HANDLER: %w{event_handler_command},
40
+ CHANGE_HOST_CHECK_COMMAND: %w{host_name check_command},
41
+ CHANGE_HOST_CHECK_TIMEPERIOD: %w{host_name check_timeperod},
42
+ CHANGE_HOST_CHECK_TIMEPERIOD: %w{host_name timeperiod},
43
+ CHANGE_HOST_EVENT_HANDLER: %w{host_name event_handler_command},
44
+ CHANGE_HOST_MODATTR: %w{host_name value},
45
+ CHANGE_MAX_HOST_CHECK_ATTEMPTS: %w{host_name check_attempts},
46
+ CHANGE_MAX_SVC_CHECK_ATTEMPTS: %w{host_name service_description check_attempts},
47
+ CHANGE_NORMAL_HOST_CHECK_INTERVAL: %w{host_name check_interval},
48
+ CHANGE_NORMAL_SVC_CHECK_INTERVAL: %w{host_name service_description check_interval},
49
+ CHANGE_RETRY_HOST_CHECK_INTERVAL: %w{host_name service_description check_interval},
50
+ CHANGE_RETRY_SVC_CHECK_INTERVAL: %w{host_name service_description check_interval},
51
+ CHANGE_SVC_CHECK_COMMAND: %w{host_name service_description check_command},
52
+ CHANGE_SVC_CHECK_TIMEPERIOD: %w{host_name service_description check_timeperiod},
53
+ CHANGE_SVC_EVENT_HANDLER: %w{host_name service_description event_handler_command},
54
+ CHANGE_SVC_MODATTR: %w{host_name service_description value},
55
+ CHANGE_SVC_NOTIFICATION_TIMEPERIOD: %w{host_name service_description notification_timeperiod},
56
+ DELAY_HOST_NOTIFICATION: %w{host_name notification_time},
57
+ DELAY_SVC_NOTIFICATION: %w{host_name service_description notification_time},
58
+ DEL_ALL_HOST_COMMENTS: %w{host_name},
59
+ DEL_ALL_SVC_COMMENTS: %w{host_name service_description},
60
+ DEL_HOST_COMMENT: %w{comment_id},
61
+ DEL_HOST_DOWNTIME: %w{downtime_id},
62
+ DEL_SVC_COMMENT: %w{comment_id},
63
+ DEL_SVC_DOWNTIME: %w{downtime_id},
64
+ DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST: %w{host_name},
65
+ DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS: %w{contactgroup_name},
66
+ DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS: %w{contactgroup_name},
67
+ DISABLE_CONTACT_HOST_NOTIFICATIONS: %w{contact_name},
68
+ DISABLE_CONTACT_SVC_NOTIFICATIONS: %w{contact_name},
69
+ DISABLE_EVENT_HANDLERS: [],
70
+ DISABLE_FAILURE_PREDICTION: [],
71
+ DISABLE_FLAP_DETECTION: [],
72
+ DISABLE_HOSTGROUP_HOST_CHECKS: %w{hostgroup_name},
73
+ DISABLE_HOSTGROUP_HOST_NOTIFICATIONS: %w{hostgroup_name},
74
+ DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS: %w{hostgroup_name},
75
+ DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS: %w{hostgroup_name},
76
+ DISABLE_HOSTGROUP_SVC_CHECKS: %w{hostgroup_name},
77
+ DISABLE_HOSTGROUP_SVC_NOTIFICATIONS: %w{hostgroup_name},
78
+ DISABLE_HOST_AND_CHILD_NOTIFICATIONS: %w{host_name},
79
+ DISABLE_HOST_CHECK: %w{host_name},
80
+ DISABLE_HOST_EVENT_HANDLER: %w{host_name},
81
+ DISABLE_HOST_FLAP_DETECTION: %w{host_name},
82
+ DISABLE_HOST_FRESHNESS_CHECKS: [],
83
+ DISABLE_HOST_NOTIFICATIONS: %w{host_name},
84
+ DISABLE_HOST_SVC_CHECKS: %w{host_name},
85
+ DISABLE_HOST_SVC_NOTIFICATIONS: %w{host_name},
86
+ DISABLE_NOTIFICATIONS: [],
87
+ DISABLE_PASSIVE_HOST_CHECKS: %w{host_name},
88
+ DISABLE_PASSIVE_SVC_CHECKS: %w{host_name service_description},
89
+ DISABLE_PERFORMANCE_DATA: [],
90
+ DISABLE_SERVICEGROUP_HOST_CHECKS: %w{servicegroup_name},
91
+ DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS: %w{servicegroup_name},
92
+ DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS: %w{servicegroup_name},
93
+ DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS: %w{servicegroup_name},
94
+ DISABLE_SERVICEGROUP_SVC_CHECKS: %w{servicegroup_name},
95
+ DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS: %w{servicegroup_name},
96
+ DISABLE_SERVICE_FLAP_DETECTION: %w{host_name service_description},
97
+ DISABLE_SERVICE_FRESHNESS_CHECKS: [],
98
+ DISABLE_SVC_CHECK: %w{host_name service_description},
99
+ DISABLE_SVC_EVENT_HANDLER: %w{host_name service_description},
100
+ DISABLE_SVC_FLAP_DETECTION: %w{host_name service_description},
101
+ DISABLE_SVC_NOTIFICATIONS: %w{host_name service_description},
102
+ ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST: %w{host_name},
103
+ ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS: %w{contactgroup_name},
104
+ ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS: %w{contactgroup_name},
105
+ ENABLE_CONTACT_HOST_NOTIFICATIONS: %w{contact_name},
106
+ ENABLE_CONTACT_SVC_NOTIFICATIONS: %w{contact_name},
107
+ ENABLE_EVENT_HANDLERS: [],
108
+ ENABLE_FAILURE_PREDICTION: [],
109
+ ENABLE_FLAP_DETECTION: [],
110
+ ENABLE_HOSTGROUP_HOST_CHECKS: %w{hostgroup_name},
111
+ ENABLE_HOSTGROUP_HOST_NOTIFICATIONS: %w{hostgroup_name},
112
+ ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS: %w{hostgroup_name},
113
+ ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS: %w{hostgroup_name},
114
+ ENABLE_HOSTGROUP_SVC_CHECKS: %w{hostgroup_name},
115
+ ENABLE_HOSTGROUP_SVC_NOTIFICATIONS: %w{hostgroup_name},
116
+ ENABLE_HOST_AND_CHILD_NOTIFICATIONS: %w{host_name},
117
+ ENABLE_HOST_CHECK: %w{host_name},
118
+ ENABLE_HOST_EVENT_HANDLER: %w{host_name},
119
+ ENABLE_HOST_FLAP_DETECTION: %w{host_name},
120
+ ENABLE_HOST_FRESHNESS_CHECKS: [],
121
+ ENABLE_HOST_NOTIFICATIONS: %w{host_name},
122
+ ENABLE_HOST_SVC_CHECKS: %w{host_name},
123
+ ENABLE_HOST_SVC_NOTIFICATIONS: %w{host_name},
124
+ ENABLE_NOTIFICATIONS: [],
125
+ ENABLE_PASSIVE_HOST_CHECKS: %w{host_name},
126
+ ENABLE_PASSIVE_SVC_CHECKS: %w{host_name service_description},
127
+ ENABLE_PERFORMANCE_DATA: [],
128
+ ENABLE_SERVICEGROUP_HOST_CHECKS: %w{servicegroup_name},
129
+ ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS: %w{servicegroup_name},
130
+ ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS: %w{servicegroup_name},
131
+ ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS: %w{servicegroup_name},
132
+ ENABLE_SERVICEGROUP_SVC_CHECKS: %w{servicegroup_name},
133
+ ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS: %w{servicegroup_name},
134
+ ENABLE_SERVICE_FRESHNESS_CHECKS: [],
135
+ ENABLE_SVC_CHECK: %w{host_name service_description},
136
+ ENABLE_SVC_EVENT_HANDLER: %w{host_name service_description},
137
+ ENABLE_SVC_FLAP_DETECTION: %w{host_name service_description},
138
+ ENABLE_SVC_NOTIFICATIONS: %w{host_name service_description},
139
+ PROCESS_FILE: %w{file_name delete},
140
+ PROCESS_HOST_CHECK_RESULT: %w{host_name status_code plugin_output},
141
+ PROCESS_SERVICE_CHECK_RESULT: %w{host_name service_description return_code plugin_output},
142
+ READ_STATE_INFORMATION: [],
143
+ REMOVE_HOST_ACKNOWLEDGEMENT: %w{host_name},
144
+ REMOVE_SVC_ACKNOWLEDGEMENT: %w{host_name service_description},
145
+ RESTART_PROGRAM: [],
146
+ SAVE_STATE_INFORMATION: [],
147
+ SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME: %w{host_name start_time end_time fixed trigger_id duration author comment},
148
+ SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME: %w{host_name start_time end_time fixed trigger_id duration author comment},
149
+ SCHEDULE_FORCED_HOST_CHECK: %w{host_name check_time},
150
+ SCHEDULE_FORCED_HOST_SVC_CHECKS: %w{host_name check_time},
151
+ SCHEDULE_FORCED_SVC_CHECK: %w{host_name service_description check_time},
152
+ SCHEDULE_HOSTGROUP_HOST_DOWNTIME: %w{hostgroup_name start_time end_time fixed trigger_id duration author comment},
153
+ SCHEDULE_HOSTGROUP_SVC_DOWNTIME: %w{hostgroup_name start_time end_time fixed trigger_id duration author comment},
154
+ SCHEDULE_HOST_CHECK: %w{host_name check_time},
155
+ SCHEDULE_HOST_DOWNTIME: %w{host_name start_time end_time fixed trigger_id duration author comment},
156
+ SCHEDULE_HOST_SVC_CHECKS: %w{host_name check_time},
157
+ SCHEDULE_HOST_SVC_DOWNTIME: %w{host_name start_time end_time fixed trigger_id duration author comment},
158
+ SCHEDULE_SERVICEGROUP_HOST_DOWNTIME: %w{servicegroup_name start_time end_time fixed trigger_id duration author comment},
159
+ SCHEDULE_SERVICEGROUP_SVC_DOWNTIME: %w{servicegroup_name start_time end_time fixed trigger_id duration author comment},
160
+ SCHEDULE_SVC_CHECK: %w{host_name service_description check_time},
161
+ SCHEDULE_SVC_DOWNTIME: %w{host_name service_desription start_time end_time fixed trigger_id duration author comment},
162
+ SEND_CUSTOM_HOST_NOTIFICATION: %w{host_name options author comment},
163
+ SEND_CUSTOM_SVC_NOTIFICATION: %w{host_name service_description options author comment},
164
+ SET_HOST_NOTIFICATION_NUMBER: %w{host_name notification_number},
165
+ SET_SVC_NOTIFICATION_NUMBER: %w{host_name service_description notification_number},
166
+ SHUTDOWN_PROGRAM: [],
167
+ START_ACCEPTING_PASSIVE_HOST_CHECKS: [],
168
+ START_ACCEPTING_PASSIVE_SVC_CHECKS: [],
169
+ START_EXECUTING_HOST_CHECKS: [],
170
+ START_EXECUTING_SVC_CHECKS: [],
171
+ START_OBSESSING_OVER_HOST: %w{host_name},
172
+ START_OBSESSING_OVER_HOST_CHECKS: [],
173
+ START_OBSESSING_OVER_SVC: %w{host_name service_description},
174
+ START_OBSESSING_OVER_SVC_CHECKS: [],
175
+ STOP_ACCEPTING_PASSIVE_HOST_CHECKS: [],
176
+ STOP_ACCEPTING_PASSIVE_SVC_CHECKS: [],
177
+ STOP_EXECUTING_HOST_CHECKS: [],
178
+ STOP_EXECUTING_SVC_CHECKS: [],
179
+ STOP_OBSESSING_OVER_HOST: %w{host_name},
180
+ STOP_OBSESSING_OVER_HOST_CHECKS: [],
181
+ STOP_OBSESSING_OVER_SVC: %w{host_name service_description},
182
+ STOP_OBSESSING_OVER_SVC_CHECKS: []
183
+ }.freeze
184
+ end
185
+ end
186
+
@@ -0,0 +1,142 @@
1
+ module Nagios
2
+
3
+
4
+ # Class Nagios::ExternalCommands is class implementing sending
5
+ # commands to external commands file in Nagios.
6
+ #
7
+ # From nagios.cfg file:
8
+ #
9
+ # This is the file that Nagios checks for external command requests.
10
+ # It is also where the command CGI will write commands that are
11
+ # submitted by users, so it must be writable by the user that the
12
+ # web server is running as (usually 'nobody').
13
+ #
14
+ # == Usage
15
+ #
16
+ # command = Nagios::ExternalCommands.new Nagios::Config.new.parse.command_file
17
+ #
18
+ # command.write :action => :PROCESS_HOST_CHECK_RESULT,
19
+ # :host_name => 'myhost', :status_code => 0, :plugin_output => "PING command OK"
20
+ #
21
+ class ExternalCommands
22
+
23
+ require 'erb'
24
+ require_relative 'external_commands/list'
25
+
26
+ # Constructor for the external command write class.
27
+ #
28
+ # @param [String] path Full UNIX path to external command file
29
+ #
30
+ # == Example
31
+ #
32
+ # >> cmd = Nagios::ExternalCommands.new('/var/nagios/rw/nagios.cmd')
33
+ #
34
+ def initialize path
35
+ raise ArgumentError, "External command file name must be provided" unless path
36
+ raise RuntimeError, "External command directory holding file #{path} is not writable by this user." unless File.writable? File.dirname path
37
+
38
+ @path = path
39
+ end
40
+
41
+ attr_reader :path
42
+
43
+ # Action to write: one of the keys listed in
44
+ # ::Nagios::ExternalCommands::ACTIONS hash.
45
+ attr_accessor :action
46
+
47
+ # Time-stamp - usually time when write is performed, but can be
48
+ # overridden by params[:ts] in constructor. If given as argument
49
+ # for constructor it should be String of the format:
50
+ # Time.to_i.to_s (i.e number of seconds since epoch).
51
+ attr_accessor :ts
52
+
53
+ # TODO: make int dynamically later with:
54
+ # >> Nagios::ExternalCommands::ACTIONS.values.flatten.uniq
55
+ # This returns full list of Nagios variables used in external commands
56
+ #
57
+
58
+ # Nagios variable used in external command
59
+ attr_accessor :host_name, :sticky, :notify, :persistent, :author,
60
+ :comment, :service_description, :contact_name,
61
+ :notification_timeperiod, :value, :varname, :varvalue,
62
+ :event_handler_command, :check_command, :timeperiod,
63
+ :check_attempts, :check_interval, :check_timeperiod,
64
+ :notification_time, :comment_id, :downtime_id, :contactgroup_name,
65
+ :hostgroup_name, :servicegroup_name, :file_name, :delete,
66
+ :status_code, :plugin_output, :return_code, :start_time,
67
+ :end_time, :fixed, :trigger_id, :duration, :check_time,
68
+ :service_desription, :start_time, :options, :notification_number
69
+
70
+ # Get private binding to use with ERB bindings.
71
+ def get_binding
72
+ binding()
73
+ end
74
+
75
+ # Send command to Nagios. Prints formatted string to external command file (pipe).
76
+ #
77
+ # @param [Hash or Array] data Data to write to command file pipe. Must
78
+ # include :action and all additional variables
79
+ def write data
80
+ case data
81
+ when Hash then data = [data]
82
+ else
83
+ return { :result => false, :data => "Input data type #{data.class} is not supproted." }
84
+ end
85
+
86
+ result, output = true, []
87
+
88
+ data.each do |params|
89
+
90
+ messages = []
91
+
92
+ if params.has_key? :action
93
+ messages << "ArgumentError: Action name #{params[:action]} is not implemented" unless ACTIONS.keys.include? params[:action]
94
+ else
95
+ messages << "ArgumentError: Action name must be provided"
96
+ end
97
+
98
+ # It makes sense to continue only if checks above did not fail
99
+ if messages.empty?
100
+ #
101
+ # Clear all attributes first - so no old data left
102
+ #
103
+ ACTIONS.values.flatten.uniq.each do |att|
104
+ self.instance_variable_set "@#{att}", nil
105
+ end
106
+ #
107
+ # And set it to param's value
108
+ #
109
+ params.each { |k,v| self.instance_variable_set "@#{k}", v }
110
+ #
111
+ # Check that all variable that are used in the template are
112
+ # actually set, not nil's
113
+ #
114
+ ACTIONS[@action].each do |var|
115
+ messages << "ArgumentError, Parameter :#{var} is required, cannot be nil" if self.instance_variable_get("@#{var}").nil?
116
+ end
117
+
118
+ # Try to write to file only if none of the above failed
119
+ if messages.empty?
120
+ self.ts = params[:ts] || Time.now.to_i.to_s
121
+
122
+ format = "[#{ts}] " << ([self.action.to_s] + ACTIONS[self.action].map {|x| "<%= #{x} %>" }).join(';')
123
+
124
+ begin
125
+ File.open(path, 'a') do |pipe|
126
+ pipe.puts ERB.new(format).result(self.get_binding)
127
+ pipe.close
128
+ end
129
+ rescue e
130
+ messages << e.message
131
+ end
132
+ end
133
+ end
134
+
135
+ output << { data: params, result: messages.empty? , messages: messages }
136
+ end # data.each
137
+
138
+ { result: result, data: output }
139
+ end # def write
140
+ end
141
+ end
142
+