sensu-plugins-network-interface 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d710020eee74c6f67f4ddffb54681fa8a082c1f9
4
+ data.tar.gz: bf2a2743f08bf6c8bda1eecd960609ac8d0feb39
5
+ SHA512:
6
+ metadata.gz: ffb0511ef45a42c56a70573202dba316ae93139c32bac27c6f6c929b7704968317e1e8c32b57bca6177046ec51f5f826faab5d45044eb65517a4ad08fa3b006c
7
+ data.tar.gz: 25b55835363f9bada8a9ea6d7dac184e87dd100d210db1a6f6ede965cd0e222d93e895c101b48d389299c770c0b7c0265f6ea888b5f04d0e206ae8ea93e5db80
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Change Log
2
+ This project adheres to [Semantic Versioning](http://semver.org/).
3
+
4
+ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
5
+
6
+ ## Unreleased
7
+
8
+ ## [0.0.1] - 2015-12-28
9
+ ### Added
10
+ - Initial release
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2015 Matteo Cerutti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # Sensu plugin for monitoring network interfaces
2
+
3
+ A sensu plugin to efficiently monitor network interfaces on Linux allowing to track metrics like speed, duplex, operational status, link carrier etc.
4
+
5
+ The plugin generates multiple OK/WARN/CRIT/UNKNOWN events via the sensu client socket (https://sensuapp.org/docs/latest/clients#client-socket-input) so that you
6
+ do not miss state changes when monitoring multiple interfaces + metrics.
7
+
8
+ ## Usage
9
+
10
+ The plugin accepts command line options to specify things like expected mtu, speed, duplex, operstate etc.
11
+
12
+ ```
13
+ Usage: check-network-interface.rb (options)
14
+ --carrier <STATE> Indicates the current physical link state of the interface (default: up)
15
+ -c, --config <PATH> Optional configuration file (default: ./network-interface.json)
16
+ -d, --duplex <STATE> Check interface duplex settings (default: full)
17
+ -x <INTERFACES> Comma separated list of interfaces to ignore
18
+ -i <INTERFACES> Comma separated list of interfaces to check (default: ALL)
19
+ -m, --mtu <MTU> Message Transfer Unit
20
+ --operstate <STATE> Indicates the interface RFC2863 operational state (default: up)
21
+ -X <INTERFACES> Comma separated list of Interfaces to ignore (regex)
22
+ -I <INTERFACES> Comma separated list of interfaces to check (regex)
23
+ -s, --speed <SPEED> Expected speed in Mb/s
24
+ -t, --txqueuelen <TXQUEUELEN> Transmit Queue Length
25
+ -w, --warn Warn instead of throwing a critical failure
26
+ ```
27
+
28
+ By default, command line option parameters are global to all interfaces. However, each interface can override the defaults in an optional JSON configuration file which must be placed
29
+ in the same location as the plugin.
30
+
31
+ JSON example:
32
+
33
+ ```
34
+ {
35
+ "interfaces": {
36
+ "eth0": {
37
+ "operstate": "down",
38
+ "carrier": "down"
39
+ "duplex": "full",
40
+ "speed": 10000,
41
+ "mtu": 9000,
42
+ "txqueuelen": 10000
43
+ },
44
+ ...
45
+ }
46
+ }
47
+ ```
48
+
49
+ Ideally, you would manage the configuration file via your favourite cfgmgmt tool (e.g. Puppet).
50
+
51
+ ## Author
52
+ Matteo Cerutti - <matteo.cerutti@hotmail.co.uk>
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # check-network-interface.rb
4
+ #
5
+ # Author: Matteo Cerutti <matteo.cerutti@hotmail.co.uk>
6
+ #
7
+
8
+ require 'sensu-plugin/check/cli'
9
+ require 'socket'
10
+
11
+ class CheckNetworkInterface < Sensu::Plugin::Check::CLI
12
+ option :interface,
13
+ :description => "Comma separated list of interfaces to check (default: ALL)",
14
+ :short => "-i <INTERFACES>",
15
+ :proc => proc { |a| a.split(',') },
16
+ :default => []
17
+
18
+ option :rinterface,
19
+ :description => "Comma separated list of interfaces to check (regex)",
20
+ :short => "-I <INTERFACES>",
21
+ :proc => proc { |a| a.split(',') },
22
+ :default => []
23
+
24
+ option :ignore_interface,
25
+ :description => "Comma separated list of interfaces to ignore",
26
+ :short => "-x <INTERFACES>",
27
+ :proc => proc { |a| a.split(',') },
28
+ :default => []
29
+
30
+ option :rignore_interface,
31
+ :description => "Comma separated list of Interfaces to ignore (regex)",
32
+ :short => "-X <INTERFACES>",
33
+ :proc => proc { |a| a.split(',') },
34
+ :default => []
35
+
36
+ option :config_file,
37
+ :description => "Optional configuration file (default: #{File.dirname(__FILE__)}/network-interface.json)",
38
+ :short => "-c <PATH>",
39
+ :long => "--config <PATH>",
40
+ :default => File.dirname(__FILE__) + "/network-interface.json"
41
+
42
+ option :speed,
43
+ :description => "Expected speed in Mb/s",
44
+ :short => "-s <SPEED>",
45
+ :long => "--speed <SPEED>",
46
+ :proc => proc(&:to_i),
47
+ :default => nil
48
+
49
+ option :mtu,
50
+ :description => 'Message Transfer Unit',
51
+ :short => "-m <MTU>",
52
+ :long => "--mtu <MTU>",
53
+ :proc => proc(&:to_i),
54
+ :default => nil
55
+
56
+ option :txqueuelen,
57
+ :description => 'Transmit Queue Length',
58
+ :short => "-t <TXQUEUELEN>",
59
+ :long => "--txqueuelen <TXQUEUELEN>",
60
+ :proc => proc(&:to_i),
61
+ :default => nil
62
+
63
+ option :duplex,
64
+ :description => "Check interface duplex settings (default: full)",
65
+ :short => "-d <STATE>",
66
+ :long => "--duplex <STATE>",
67
+ :in => ["half", "full"],
68
+ :default => "full"
69
+
70
+ option :operstate,
71
+ :description => "Indicates the interface RFC2863 operational state (default: up)",
72
+ :long => "--operstate <STATE>",
73
+ :in => ["unknown", "notpresent", "down", "lowerlayerdown", "testing", "dormant", "up"],
74
+ :default => "up"
75
+
76
+ option :carrier,
77
+ :description => "Indicates the current physical link state of the interface (default: up)",
78
+ :long => "--carrier <STATE>",
79
+ :in => ["down", "up"],
80
+ :default => "up"
81
+
82
+ option :warn,
83
+ :description => "Warn instead of throwing a critical failure",
84
+ :short => "-w",
85
+ :long => "--warn",
86
+ :boolean => false
87
+
88
+ def initialize()
89
+ super
90
+
91
+ @interfaces = []
92
+ find_interfaces().each do |interface|
93
+ if config[:ignore_interface].size > 0
94
+ next if config[:ignore_interface].include?(interface)
95
+ end
96
+
97
+ if config[:rignore_interface].size > 0
98
+ b = false
99
+ config[:rignore_interface].each do |ignore_interface|
100
+ if interface =~ Regexp.new(ignore_interface)
101
+ b = true
102
+ break
103
+ end
104
+ end
105
+ next if b
106
+ end
107
+
108
+ if config[:interface].size > 0
109
+ next unless config[:interface].include?(interface)
110
+ end
111
+
112
+ if config[:rinterface].size > 0
113
+ b = true
114
+ config[:rinterface].each do |rinterface|
115
+ if interface =~ Regexp.new(rinterface)
116
+ b = false
117
+ break
118
+ end
119
+ end
120
+ next if b
121
+ end
122
+
123
+ @interfaces << interface
124
+ end
125
+
126
+ @json_config = nil
127
+ if File.exists?(config[:config_file])
128
+ require 'json'
129
+ @json_config = JSON.parse(File.read(config[:config_file]))
130
+ end
131
+ end
132
+
133
+ def send_client_socket(data)
134
+ sock = UDPSocket.new
135
+ sock.send(data + "\n", 0, "127.0.0.1", 3030)
136
+ end
137
+
138
+ def send_ok(check_name, msg)
139
+ event = {"name" => check_name, "status" => 0, "output" => "OK: #{msg}", "handler" => config[:handler]}
140
+ send_client_socket(event.to_json)
141
+ end
142
+
143
+ def send_warning(check_name, msg)
144
+ event = {"name" => check_name, "status" => 1, "output" => "WARNING: #{msg}", "handler" => config[:handler]}
145
+ send_client_socket(event.to_json)
146
+ end
147
+
148
+ def send_critical(check_name, msg)
149
+ event = {"name" => check_name, "status" => 2, "output" => "CRITICAL: #{msg}", "handler" => config[:handler]}
150
+ send_client_socket(event.to_json)
151
+ end
152
+
153
+ def send_unknown(check_name, msg)
154
+ event = {"name" => check_name, "status" => 3, "output" => "UNKNOWN: #{msg}", "handler" => config[:handler]}
155
+ send_client_socket(event.to_json)
156
+ end
157
+
158
+ def find_interfaces()
159
+ Dir["/sys/class/net/*"].map { |i| File.basename(i) }.reject { |i| i =~ /^lo/ }
160
+ end
161
+
162
+ def get_info(interface)
163
+ info = {}
164
+
165
+ # https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
166
+ ["tx_queue_len", "speed", "mtu", "duplex", "carrier", "operstate"].each do |metric|
167
+ if File.exists?("/sys/class/net/#{interface}/#{metric}")
168
+ value = File.read("/sys/class/net/#{interface}/#{metric}").chomp
169
+
170
+ case metric
171
+ when "speed", "mtu"
172
+ info[metric] = value.to_i
173
+
174
+ when "tx_queue_len"
175
+ info['txqueuelen'] = value.to_i
176
+
177
+ when "carrier"
178
+ info[metric] = value.to_i > 0 ? "up" : "down"
179
+
180
+ else
181
+ info[metric] = value
182
+ end
183
+ else
184
+ info[metric] = nil
185
+ end
186
+ end
187
+
188
+ info
189
+ end
190
+
191
+ def run
192
+ problems = 0
193
+
194
+ @interfaces.each do |interface|
195
+ get_info(interface).each do |metric, value|
196
+ check_name = "network-interface-#{interface}-#{metric}"
197
+
198
+ if value != nil
199
+ if @json_config.has_key?('interfaces') and @json_config['interfaces'].has_key?(interface) and @json_config['interfaces'][interface].has_key?(metric)
200
+ if value != @json_config['interfaces'][interface][metric]
201
+ msg = "Expected #{metric} #{@json_config['interfaces'][interface][metric]} but found #{value} on #{interface}"
202
+ if config[:warn]
203
+ send_warning(check_name, msg)
204
+ else
205
+ send_critical(check_name, msg)
206
+ end
207
+ problems += 1
208
+ else
209
+ send_ok(check_name, "Found expected #{metric} (#{@json_config['interfaces'][interface][metric]}) on #{interface}")
210
+ end
211
+ else
212
+ if config[metric.to_sym] != nil
213
+ if value != config[metric.to_sym]
214
+ msg = "Expected #{metric} #{config[metric.to_sym]} but found #{value} on #{interface}"
215
+ if config[:warn]
216
+ send_warning(check_name, msg)
217
+ else
218
+ send_critical(check_name, msg)
219
+ end
220
+ problems += 1
221
+ else
222
+ send_ok(check_name, "Found expected #{metric} (#{config[metric.to_sym]}) on #{interface}")
223
+ end
224
+ else
225
+ send_ok(check_name, "#{metric} #{interface}")
226
+ end
227
+ end
228
+ else
229
+ send_unknown(check_name, "Failed to look up #{metric} on #{interface}")
230
+ problems += 1
231
+ end
232
+ end
233
+ end
234
+
235
+ if problems > 0
236
+ message "Found #{problems} problems"
237
+ warning if config[:warn]
238
+ critical
239
+ else
240
+ ok "All interfaces (#{@interfaces.join(', ')}) are matching the specified settings"
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,26 @@
1
+ {
2
+ "interfaces": {
3
+ "eth0": {
4
+ "operstate": "down",
5
+ "carrier": "down"
6
+ },
7
+ "eth1": {
8
+ "operstate": "down",
9
+ "carrier": "down"
10
+ },
11
+ "eth2": {
12
+ "operstate": "up",
13
+ "carrier": "up",
14
+ "speed": 10000,
15
+ "mtu": 9000,
16
+ "txqueuelen": 10000
17
+ },
18
+ "eth3": {
19
+ "operstate": "up",
20
+ "carrier": "up",
21
+ "speed": 10000,
22
+ "mtu": 9000,
23
+ "txqueuelen": 10000
24
+ }
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ require 'sensu-plugins-network-interface/version'
@@ -0,0 +1,9 @@
1
+ module SensuPluginsNetworkInterface
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 1
6
+
7
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sensu-plugins-network-interface
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Matteo Cerutti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sensu-plugin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.0
27
+ description: This plugin provides facilities to monitoring network interfaces on Linux
28
+ email: "<matteo.cerutti@hotmail.co.uk>"
29
+ executables:
30
+ - check-network-interface.rb
31
+ - network-interface.json.example
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE
37
+ - README.md
38
+ - bin/check-network-interface.rb
39
+ - bin/network-interface.json.example
40
+ - lib/sensu-plugins-network-interface.rb
41
+ - lib/sensu-plugins-network-interface/version.rb
42
+ homepage: https://github.com/m4ce/sensu-plugins-network-interface
43
+ licenses:
44
+ - MIT
45
+ metadata:
46
+ maintainer: "@m4ce"
47
+ development_status: active
48
+ production_status: stable
49
+ release_draft: 'false'
50
+ release_prerelease: 'false'
51
+ post_install_message: You can use the embedded Ruby by setting EMBEDDED_RUBY=true
52
+ in /etc/default/sensu
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.9.3
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.4.5.1
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Sensu plugins for monitoring network interfaces on Linux
72
+ test_files: []