nagiosharder 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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Joshua Nichols
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ = nagiosharder
2
+
3
+ Query and command a Nagios install using the power of ruby.
4
+
5
+ require 'nagiosharder'
6
+ site = NagiosHarder::Site.new('http://path/to/nagios/cgi/directory', 'user', 'password', 'version')
7
+ # version defaults to 3
8
+
9
+ # get details back about a host's services
10
+ puts site.host_status('myhost')
11
+
12
+ # schedule a host to have services checks run again right now
13
+ site.schedule_host_check('myhost')
14
+
15
+ # schedule a host to have services checks run again right now
16
+ site.schedule_service_check('myhost', 'myservice')
17
+
18
+ # schedule 20 minutes of downtime, starting now
19
+ site.schedule_host_downtime('myhost', :start_time => Time.now, :end_time => Time.now + 20.minutes)
20
+
21
+ # schedule a flexible 20 minutes of downtime between now and 2 hours from now
22
+ site.schedule_host_downtime('myhost', :type => :flexible, :start_time => Time.now, :end_time => Time.now + 2.hours, :hours => 0, :minutes => 20)
23
+
24
+ # acknowledge a down service
25
+ site.acknowledge_service('myhost', 'myservice', 'something bad happened')
26
+
27
+ # or unacknowledge
28
+ site.unacknowledge_service('myhost', 'myservice')
29
+
30
+ To be continue?
31
+
32
+ == Note on Patches/Pull Requests
33
+
34
+ * Fork the project.
35
+ * Make your feature addition or bug fix.
36
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
37
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
38
+ * Send me a pull request. Bonus points for topic branches.
39
+
40
+ == Copyright
41
+
42
+ Copyright (c) 2010 Josh Nichols. See LICENSE for details.
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "nagiosharder"
8
+ gem.version = "0.1.0"
9
+ gem.summary = %Q{Nagios access at your ruby fingertips}
10
+ gem.description = %Q{Nagios access at your ruby fingertips}
11
+ gem.email = "josh@technicalpickles.com"
12
+ gem.homepage = "http://github.com/railsmachine/nagiosharder"
13
+ gem.authors = ["Joshua Nichols"]
14
+ gem.add_dependency 'rest-client', '~> 1.6.1'
15
+ gem.add_dependency 'nokogiri', '~> 1.4.3'
16
+ gem.add_dependency 'activesupport', '~> 3.0.3'
17
+ gem.add_dependency 'httparty', '~> 0.6.1'
18
+ gem.add_development_dependency "rspec", ">= 1.2.9"
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "nagiosharder #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
@@ -0,0 +1,288 @@
1
+ require 'restclient'
2
+ require 'nokogiri'
3
+ require 'active_support/core_ext/array'
4
+ require 'active_support/core_ext/numeric/time'
5
+ require 'active_support/core_ext/time/calculations'
6
+ require 'active_support/core_ext/date/calculations'
7
+ require 'active_support/core_ext/date_time/calculations'
8
+ require 'active_support/core_ext/date/acts_like'
9
+ require 'active_support/core_ext/time/acts_like'
10
+ require 'active_support/core_ext/date_time/acts_like'
11
+ require 'httparty'
12
+
13
+ class NagiosHarder
14
+ class Site
15
+ attr_accessor :nagios_url, :user, :password, :default_options, :default_cookies, :version
16
+ include HTTParty::ClassMethods
17
+
18
+ def initialize(nagios_url, user, password, version = 3)
19
+ @nagios_url = nagios_url.gsub(/\/$/, '')
20
+ @user = user
21
+ @password = password
22
+ @default_options = {}
23
+ @default_cookies = {}
24
+ @version = version
25
+ basic_auth(@user, @password) if @user && @password
26
+ end
27
+
28
+ def acknowledge_service(host, service, comment)
29
+ # extra options: sticky_arg, send_notification, persistent
30
+
31
+ request = {
32
+ :cmd_typ => 34,
33
+ :cmd_mod => 2,
34
+ :com_author => @user,
35
+ :com_data => comment,
36
+ :host => host,
37
+ :service => service
38
+ }
39
+
40
+ response = post(cmd_url, :body => request)
41
+ response.code == 200 && response.body =~ /successful/
42
+ end
43
+
44
+ def unacknowledge_service(host, service)
45
+ request = {
46
+ :cmd_typ => 52,
47
+ :cmd_mod => 2,
48
+ :host => host,
49
+ :service => service
50
+ }
51
+
52
+ response = post(cmd_url, :body => request)
53
+ response.code == 200 && response.body =~ /successful/
54
+ end
55
+
56
+ def schedule_host_downtime(host, options = {})
57
+ request = {
58
+ :cmd_mod => 2,
59
+ :cmd_typ => 55,
60
+ :com_author => options[:author] || "#{@user} via nagiosharder",
61
+ :com_data => options[:comment] || 'scheduled downtime by nagiosharder',
62
+ :host => host,
63
+ :childoptions => 0,
64
+ :trigger => 0
65
+ }
66
+
67
+ # FIXME we could use some option checking...
68
+
69
+ request[:type] = case options[:type].to_sym
70
+ when :fixed then 1
71
+ when :flexible then 0
72
+ else 1 # default to fixed
73
+ end
74
+
75
+ if request[:type] == 0
76
+ request[:hours] = options[:hours]
77
+ request[:minutes] = options[:minutes]
78
+ end
79
+
80
+ request[:start_time] = formatted_time_for(options[:start_time])
81
+ request[:end_time] = formatted_time_for(options[:end_time])
82
+
83
+ response = post(cmd_url, :body => request)
84
+
85
+ response.code == 200 && response.body =~ /successful/
86
+ end
87
+
88
+ # FIXME need to confirm this functionality exists in nagios
89
+ #def cancel_downtime(downtime_id, downtime_type = :host_downtime)
90
+ # downtime_types = {
91
+ # :host_downtime => 78,
92
+ # :service_downtime => 79
93
+ # }
94
+ # response = post(cmd_url, :body => {
95
+ # :cmd_typ => downtime_types[downtime_type],
96
+ # :cmd_mod => 2,
97
+ # :down_id => downtime_id
98
+ # })
99
+ # response.code == 200 && response.body =~ /successful/
100
+ #end
101
+
102
+ def schedule_host_check(host)
103
+ response = post(cmd_url, :body => {
104
+ :start_time => formatted_time_for(Time.now),
105
+ :host => host,
106
+ :force_check => true,
107
+ :cmd_typ => 96,
108
+ :cmd_mod => 2
109
+ })
110
+ response.code == 200 && response.body =~ /successful/
111
+ end
112
+
113
+ def schedule_service_check(host, service)
114
+ response = post(cmd_url, :body => {
115
+ :start_time => formatted_time_for(Time.now),
116
+ :host => host,
117
+ :service => service,
118
+ :force_check => true,
119
+ :cmd_typ => 7,
120
+ :cmd_mod => 2
121
+ })
122
+ response.code == 200 && response.body =~ /successful/
123
+ end
124
+
125
+ def service_status(type, options = {})
126
+ service_status_type = case type
127
+ when :ok then 2
128
+ when :warning then 4
129
+ when :unknown then 8
130
+ when :critical then 16
131
+ when :pending then 1
132
+ when :all_problems then 28
133
+ when :all then nil
134
+ else
135
+ raise "Unknown type"
136
+ end
137
+
138
+ sort_type = case options[:sort_type]
139
+ when :asc then 1
140
+ when :desc then 2
141
+ when nil then nil
142
+ else
143
+ raise "Invalid options[:sort_type]"
144
+ end
145
+
146
+ sort_option = case options[:sort_option]
147
+ when :host then 1
148
+ when :service then 2
149
+ when :status then 3
150
+ when :last_check then 4
151
+ when :duration then 6
152
+ when :attempts then 5
153
+ when nil then nil
154
+ else
155
+ raise "Invalid options[:sort_option]"
156
+ end
157
+
158
+
159
+ params = {
160
+ 'hoststatustype' => 15,
161
+ 'servicestatustype' => service_status_type,
162
+ 'host' => 'all'
163
+ }
164
+
165
+
166
+ params = if @version == 3
167
+ [ "servicegroup=all", "style=detail" ]
168
+ else
169
+ [ "host=all" ]
170
+ end
171
+ params += [
172
+ service_status_type ? "servicestatustypes=#{service_status_type}" : nil,
173
+ sort_type ? "sorttype=#{sort_type}" : nil,
174
+ sort_option ? "sortoption=#{sort_option}" : nil,
175
+ "hoststatustypes=15"
176
+ ]
177
+ query = params.compact.join('&')
178
+ url = "#{status_url}?#{query}"
179
+ response = get(url)
180
+
181
+ raise "wtf #{url}? #{response.code}" unless response.code == 200
182
+
183
+ statuses = []
184
+ parse_status_html(response) do |status|
185
+ statuses << status
186
+ end
187
+
188
+ statuses
189
+ end
190
+
191
+ def host_status(host)
192
+ host_status_url = "#{status_url}?host=#{host}"
193
+ response = get(host_status_url)
194
+
195
+ raise "wtf #{host_status_url}? #{response.code}" unless response.code == 200
196
+
197
+ services = {}
198
+ parse_status_html(response) do |status|
199
+ services[status[:service]] = status
200
+ end
201
+
202
+ services
203
+ end
204
+
205
+ def status_url
206
+ "#{nagios_url}/status.cgi"
207
+ end
208
+
209
+ def cmd_url
210
+ "#{nagios_url}/cmd.cgi"
211
+ end
212
+
213
+ private
214
+
215
+
216
+ def formatted_time_for(time)
217
+ if @version.to_i < 3
218
+ time.strftime("%m-%d-%Y %H:%M:%S")
219
+ else
220
+ time.strftime("%Y-%m-%d %H:%M:%S")
221
+ end
222
+ end
223
+
224
+ def parse_status_html(response)
225
+ doc = Nokogiri::HTML(response)
226
+ rows = doc.css('table.status > tr')
227
+
228
+ last_host = nil
229
+ rows.each do |row|
230
+ columns = Nokogiri::HTML(row.inner_html).css('body > td').to_a
231
+ if columns.any?
232
+
233
+ host = columns[0].inner_text.gsub(/\n/, '')
234
+
235
+ # for a given host, the host details are blank after the first row
236
+ if host != ''
237
+ # remember it for next time
238
+ last_host = host
239
+ else
240
+ # or save it for later
241
+ host = last_host
242
+ end
243
+
244
+ #require 'ruby-debug'; breakpoint
245
+ if columns[1]
246
+ service_links = columns[1].css('td a')
247
+ service = service_links[0].inner_html
248
+ acknowledged = service_links.size == 3 # acknowledged servies have a link to the service, link to comments, and a link to unacknowledge
249
+ end
250
+
251
+ status = columns[2].inner_html if columns[2]
252
+ last_check = columns[3].inner_html if columns[3]
253
+ duration = columns[4].inner_html if columns[4]
254
+ started_at = if duration && match_data = duration.match(/^\s*(\d+)d\s+(\d+)h\s+(\d+)m\s+(\d+)s\s*$/)
255
+ (
256
+ match_data[1].to_i.days +
257
+ match_data[2].to_i.hours +
258
+ match_data[3].to_i.minutes +
259
+ match_data[4].to_i.seconds
260
+ ).ago
261
+
262
+ end
263
+ attempts = columns[5].inner_html if columns[5]
264
+ status_info = columns[6].inner_html.gsub('&nbsp;', '') if columns[6]
265
+
266
+ status = {
267
+ :host => host,
268
+ :service => service,
269
+ :status => status,
270
+ :last_check => last_check,
271
+ :duration => duration,
272
+ :attempts => attempts,
273
+ :started_at => started_at,
274
+ :extended_info => status_info,
275
+ :acknowledged => acknowledged
276
+ }
277
+
278
+ if host && service && status && last_check && duration && attempts && started_at && status_info
279
+ yield status
280
+ end
281
+ end
282
+ end
283
+
284
+ nil
285
+ end
286
+
287
+ end
288
+ end
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{nagiosharder}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Joshua Nichols"]
12
+ s.date = %q{2011-01-17}
13
+ s.description = %q{Nagios access at your ruby fingertips}
14
+ s.email = %q{josh@technicalpickles.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "lib/nagiosharder.rb",
25
+ "nagiosharder.gemspec",
26
+ "spec/nagiosharder_spec.rb",
27
+ "spec/spec.opts",
28
+ "spec/spec_helper.rb"
29
+ ]
30
+ s.homepage = %q{http://github.com/railsmachine/nagiosharder}
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.3.7}
33
+ s.summary = %q{Nagios access at your ruby fingertips}
34
+ s.test_files = [
35
+ "spec/nagiosharder_spec.rb",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+
39
+ if s.respond_to? :specification_version then
40
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
41
+ s.specification_version = 3
42
+
43
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<rest-client>, ["~> 1.6.1"])
45
+ s.add_runtime_dependency(%q<nokogiri>, ["~> 1.4.3"])
46
+ s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.3"])
47
+ s.add_runtime_dependency(%q<httparty>, ["~> 0.6.1"])
48
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
49
+ else
50
+ s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
51
+ s.add_dependency(%q<nokogiri>, ["~> 1.4.3"])
52
+ s.add_dependency(%q<activesupport>, ["~> 3.0.3"])
53
+ s.add_dependency(%q<httparty>, ["~> 0.6.1"])
54
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
58
+ s.add_dependency(%q<nokogiri>, ["~> 1.4.3"])
59
+ s.add_dependency(%q<activesupport>, ["~> 3.0.3"])
60
+ s.add_dependency(%q<httparty>, ["~> 0.6.1"])
61
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Nagiosharder" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'nagiosharder'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nagiosharder
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Joshua Nichols
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-17 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rest-client
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 6
33
+ - 1
34
+ version: 1.6.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 1
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 3
50
+ version: 1.4.3
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: activesupport
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 1
62
+ segments:
63
+ - 3
64
+ - 0
65
+ - 3
66
+ version: 3.0.3
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 5
78
+ segments:
79
+ - 0
80
+ - 6
81
+ - 1
82
+ version: 0.6.1
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: rspec
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 13
94
+ segments:
95
+ - 1
96
+ - 2
97
+ - 9
98
+ version: 1.2.9
99
+ type: :development
100
+ version_requirements: *id005
101
+ description: Nagios access at your ruby fingertips
102
+ email: josh@technicalpickles.com
103
+ executables: []
104
+
105
+ extensions: []
106
+
107
+ extra_rdoc_files:
108
+ - LICENSE
109
+ - README.rdoc
110
+ files:
111
+ - .document
112
+ - LICENSE
113
+ - README.rdoc
114
+ - Rakefile
115
+ - lib/nagiosharder.rb
116
+ - nagiosharder.gemspec
117
+ - spec/nagiosharder_spec.rb
118
+ - spec/spec.opts
119
+ - spec/spec_helper.rb
120
+ has_rdoc: true
121
+ homepage: http://github.com/railsmachine/nagiosharder
122
+ licenses: []
123
+
124
+ post_install_message:
125
+ rdoc_options: []
126
+
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ requirements: []
148
+
149
+ rubyforge_project:
150
+ rubygems_version: 1.3.7
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: Nagios access at your ruby fingertips
154
+ test_files:
155
+ - spec/nagiosharder_spec.rb
156
+ - spec/spec_helper.rb