rubix 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +34 -198
- data/VERSION +1 -1
- data/lib/rubix.rb +11 -0
- data/lib/rubix/auto_sender.rb +108 -17
- data/lib/rubix/connection.rb +9 -0
- data/lib/rubix/monitors/monitor.rb +1 -1
- data/spec/rubix/connection_spec.rb +6 -0
- data/spec/support/integration_helper.rb +1 -1
- data/spec/test.yml +7 -7
- metadata +146 -126
data/README.rdoc
CHANGED
@@ -1,30 +1,17 @@
|
|
1
1
|
= Rubix
|
2
2
|
|
3
|
-
Rubix is a Ruby client for Zabbix[http://www.zabbix.com/]
|
4
|
-
|
3
|
+
Rubix is a Ruby client for Zabbix[http://www.zabbix.com/] that makes
|
4
|
+
it easier to programatically control Zabbix resources so that they can
|
5
|
+
be coordinated in complex, dynamic, and distributed environments like
|
6
|
+
clouds.
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
Rubix provides a wrapper for the {Zabbix API
|
9
|
+
documentation}[http://www.zabbix.com/documentation/1.8/api] and an ORM
|
10
|
+
for resources like Hosts, HostGroups, Templates, Items, &c.
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
API}[http://www.zabbix.com/documentation/1.8/api].
|
12
|
+
Rubix also provides simple command line tools and Ruby classes that
|
13
|
+
make it easier to query Zabbix and send it data.
|
13
14
|
|
14
|
-
- Provide a command-line script that wraps the
|
15
|
-
{+zabbix_sender+}[http://www.zabbix.com/documentation/1.8/manpages/zabbix_sender]
|
16
|
-
utility, allowing it to consume JSON data and to 'auto-vivify'
|
17
|
-
hosts, hostgroups, applications, and items.
|
18
|
-
|
19
|
-
- Provide some +Monitor+ classes that make it easy to write scripts
|
20
|
-
that periodically measure something and push it to Zabbix.
|
21
|
-
|
22
|
-
- Have as few dependencies as possible: the core classes only depend
|
23
|
-
on Ruby 1.8 standard library & +JSON+ and scripts additionally
|
24
|
-
depend on +Configliere+[http://github.com/mrflip/configliere].
|
25
|
-
|
26
|
-
- Play nicely with Chef[http://www.opscode.com/chef/]
|
27
|
-
|
28
15
|
There are a lot of other projects out there that connect Ruby to
|
29
16
|
Zabbix. Here's a quick list:
|
30
17
|
|
@@ -56,20 +43,17 @@ zabbix-web[http://github.com/legiar/zabbix-web]::
|
|
56
43
|
zabcon[http://trac.red-tux.net/]::
|
57
44
|
Zabcon is a command line interface for Zabbix written in Ruby
|
58
45
|
|
59
|
-
None of these projects was satisfactory for our purposes so I decided
|
60
|
-
to write Rubix. The name is terrible but the code is better. Enjoy!
|
61
|
-
|
62
46
|
== Connections, Requests, & Responses
|
63
47
|
|
64
|
-
Getting connected is easy
|
48
|
+
Getting connected to the Zabbix API is easy
|
65
49
|
|
66
50
|
require 'rubix'
|
67
51
|
|
68
52
|
# Provide API URL & credentials. These are the defaults.
|
69
53
|
Rubix.connect('http://localhost/api_jsonrpc.php', 'admin', 'zabbix')
|
70
54
|
|
71
|
-
As per the {
|
72
|
-
documentation}[http://www.zabbix.com/documentation/1.8/api]
|
55
|
+
As per the {Zabbix API
|
56
|
+
documentation}[http://www.zabbix.com/documentation/1.8/api] each
|
73
57
|
request to the Zabbix API needs four values:
|
74
58
|
|
75
59
|
+id+::
|
@@ -116,6 +100,18 @@ issue these sorts of requests directly on the command line.
|
|
116
100
|
+zabbix_api+ lets you specify the credentials and will pretty-print
|
117
101
|
responses for you. Try <tt>zabbix_api --help</tt> for more details.
|
118
102
|
|
103
|
+
=== Logging
|
104
|
+
|
105
|
+
Rubix produces log messages at the <tt>Logger::INFO</tt> level to a
|
106
|
+
+Logger+ instance by default. When the logger severity is
|
107
|
+
<tt>Logger::DEBUG</tt> Rubix will log the request and response to
|
108
|
+
every API call it makes against the Zabbix API. This can be useful
|
109
|
+
when debugging why a particular interaction isn't working as expected.
|
110
|
+
|
111
|
+
Besides programatically modifying the logger, the log level and path
|
112
|
+
can be modified at runtime with the environment variables
|
113
|
+
+RUBIX_LOG_LEVEL+ and +RUBIX_LOG_PATH+.
|
114
|
+
|
119
115
|
== ORM
|
120
116
|
|
121
117
|
If you don't want to deal with the particulars of the Zabbix API
|
@@ -146,125 +142,8 @@ complete with host groups, templates, applications, and so on.
|
|
146
142
|
item = Rubix::Item.new(:host => host, :key => 'foo.bar.baz', :description => "Some Item", :value_type => :unsigned_int, :applications => [app])
|
147
143
|
item.save
|
148
144
|
|
149
|
-
You can also +update+ and +destroy+ resources
|
150
|
-
|
151
|
-
Only host groups, templates, hosts, applications, user macros, and
|
152
|
-
items are available at present. Other Zabbix resources (actions,
|
153
|
-
alerts, events, maps, users, &c.) can be similarly wrapped, they just
|
154
|
-
haven't been yet because we don't use them as much as we use these
|
155
|
-
core resources.
|
156
|
-
|
157
|
-
== Sender
|
158
|
-
|
159
|
-
Rubix comes with a +zabbix_pipe+ script which, coupled with the
|
160
|
-
{+zabbix_sender+}[http://www.zabbix.com/documentation/1.8/manpages/zabbix_sender]
|
161
|
-
utility, allows for writing data to Zabbix.
|
162
|
-
|
163
|
-
By the design of Zabbix, all data written via +zabbix_sender+ (and
|
164
|
-
therefore +zabbix_pipe+) must be written to items with type "Zabbix
|
165
|
-
trapper". This type instructs Zabbix to accept values written by
|
166
|
-
+zabbix_sender+.
|
167
|
-
|
168
|
-
+zabbix_pipe+ can consume data from +STDIN+, a file on disk, or a
|
169
|
-
{named pipe}[http://en.wikipedia.org/wiki/Named_pipe]. It consumes
|
170
|
-
data one line at a time from any of these sources and uses the
|
171
|
-
+zabbix_sender+ utility to send this data to a Zabbix server.
|
172
|
-
|
173
|
-
Here's an example of starting +zabbix_pipe+ and sending some data onto
|
174
|
-
Zabbix. (Credentials and addresses for the Zabbix server and the
|
175
|
-
Zabbix API can all be customized; see the <tt>--help</tt> option.)
|
176
|
-
|
177
|
-
# Send one data point -- this is tab separated!
|
178
|
-
$ echo "foo.bar.baz 123" | zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
179
|
-
# Send a bunch of data points in a file
|
180
|
-
$ cat my_data.tsv | zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
181
|
-
|
182
|
-
You can also pass the file directly:
|
183
|
-
|
184
|
-
# Send a bunch of data points in a file
|
185
|
-
$ zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group' my_data.tsv
|
186
|
-
|
187
|
-
You can also listen from a named pipe. This is useful on a
|
188
|
-
"production" system in which many processes may want to simply and
|
189
|
-
easily write somewhere without worrying about what happens.
|
190
|
-
|
191
|
-
# In the first terminal
|
192
|
-
$ mkfifo /dev/zabbix
|
193
|
-
$ zabbix_pipe --pipe=/dev/zabbix --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
194
|
-
|
195
|
-
# In another terminal
|
196
|
-
$ echo "foo.bar.baz 123" > /dev/zabbix
|
197
|
-
$ cat my_data > /dev/zabbix
|
198
|
-
|
199
|
-
In any of these modes, you can also send JSON data directly.
|
200
|
-
|
201
|
-
$ echo '{"data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
202
|
-
|
203
|
-
This simple block of JSON doesn't really add any power to
|
204
|
-
+zabbix_pipe+. What becomes more interesting is that we can wedge in
|
205
|
-
data for *diffferent* hosts, items, &c. when using JSON input:
|
206
|
-
|
207
|
-
$ echo '{"host": "My first host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
208
|
-
$ echo '{"host": "My second host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
209
|
-
$ echo '{"host": "My third host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
210
|
-
|
211
|
-
Rubix will switch hosts on the fly.
|
212
|
-
|
213
|
-
=== Auto-vivification
|
214
|
-
|
215
|
-
By default, for every item written into +zabbix_pipe+, Rubix will
|
216
|
-
first check, using the Zabbix API, whether an item with the given key
|
217
|
-
exists for the given host. If not, Rubix will create the host and
|
218
|
-
the item. You can pass a few details along with your data (when
|
219
|
-
writing in JSON format) or at startup of the +zabbix_pipe+ to tune
|
220
|
-
some of the properites of newly created hosts and items:
|
221
|
-
|
222
|
-
$ echo '{"host": "My host", "hostgroups": "Host Group 1,Host Group 2", "templates": "Template 1,Template 2", "applications": "App 1, App2", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
223
|
-
|
224
|
-
If the host 'My host' does not exist, Rubix will create it, putting in
|
225
|
-
each of the host groups 'Host Group 1' and 'Host Group 2' (which will
|
226
|
-
also be auto-vivified), and attach it to templates 'Template 1' and
|
227
|
-
'Template 2' (auto-vivified). If the item does not exist for the host
|
228
|
-
'My host', then it will be created and put inside applications 'App1'
|
229
|
-
and 'App2' (auto-vivified). The value type of the item (unsigned int,
|
230
|
-
float, character, text, &c.) will be chosen dynamically based on the
|
231
|
-
value being written. The created items will all be of the type "Zabbix
|
232
|
-
trapper" so that they can be written to.
|
233
|
-
|
234
|
-
Auto-vivification is intended to make it easy to register a lot of
|
235
|
-
dynamic hosts and items in Zabbix. This is perfect for cloud
|
236
|
-
deployments where resources to be monitored are often dynamic.
|
237
|
-
|
238
|
-
==== Failed writes
|
239
|
-
|
240
|
-
By the design of Zabbix, a newly created item of type 'Zabbix trapper'
|
241
|
-
will not accept data for some interval, typically a minute or so,
|
242
|
-
after being created. This means that when writing a series of values
|
243
|
-
for some non-existent item 'foo.bar.baz', the first write will cause
|
244
|
-
the item to be created (auto-vivified), the next several writes will
|
245
|
-
fail as the Zabbix server is not accepting writes for this item yet,
|
246
|
-
and then all writes will begin to succeed as the Zabbix server catches
|
247
|
-
up. If it is absolutely essential for all writes to succeed,
|
248
|
-
including the first, then +zabbix_pipe+ needs to go to sleep for a
|
249
|
-
while after creating a new item in order to give the Zabbix server
|
250
|
-
time to catch up. This can be configured with the
|
251
|
-
<tt>--create_item_sleep</tt> option. By default this is set to 0.
|
252
|
-
|
253
|
-
==== Skipping auto-vivification
|
254
|
-
|
255
|
-
Attempting to auto-vivify keys on every single write is expensive and
|
256
|
-
does not scale. It's recommended, therefore, to run +zabbix_pipe+
|
257
|
-
with the <tt>--fast</tt> flag in production settings. In this mode,
|
258
|
-
+zabbix_pipe+ will not attempt to auto-vivify anything -- if items do
|
259
|
-
not exist, writes will just fail, as they do with +zabbix_sender+
|
260
|
-
itself.
|
261
|
-
|
262
|
-
A good pattern is to set up a production pipe (in <tt>--fast</tt>)
|
263
|
-
mode at <tt>/dev/zabbix</tt> and to do all development/deployment with
|
264
|
-
a separate instance of +zabbix_pipe+. Once development/deployment is
|
265
|
-
complete and all hosts, groups, templates, applications, and items
|
266
|
-
have been created, switch to writing all data in "production mode"
|
267
|
-
using the <tt>--fast</tt> pipe at <tt>/dev/zabbix</tt>.
|
145
|
+
You can also +update+ and +destroy+ resources as well as probe
|
146
|
+
associations: <tt>host.items</tt>.
|
268
147
|
|
269
148
|
== Monitors
|
270
149
|
|
@@ -288,66 +167,23 @@ used memory in bytes.
|
|
288
167
|
|
289
168
|
MemoryMonitor.run if $0 == __FILE__
|
290
169
|
|
291
|
-
The file <tt>memory_monitor.rb</tt> can now be run on the command line
|
292
|
-
various ways
|
170
|
+
The file <tt>memory_monitor.rb</tt> can now be run on the command line
|
171
|
+
in various ways. Most simply it will just output a measurement.
|
293
172
|
|
294
|
-
# Write the output to STDOUT
|
295
173
|
$ ruby memory_monitor.rb
|
296
174
|
'mem.used' 11595908
|
297
175
|
|
298
|
-
|
299
|
-
$ ruby memory_monitor.rb --loop=30
|
176
|
+
You can also have it loop after a number of seconds
|
300
177
|
|
178
|
+
$ ruby memory_monitor.rb --loop=30
|
301
179
|
'mem.used' 11595760
|
302
180
|
'mem.used' 11595800
|
303
181
|
'mem.used' 11596016
|
304
182
|
'mem.used' 11596008
|
305
183
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
=== Monitors with Chef
|
311
|
-
|
312
|
-
It's useful to be able to monitor resources defined in
|
313
|
-
Chef[http://www.opscode.com/chef/] and so Rubix comes with a
|
314
|
-
+ChefMonitor+ class.
|
315
|
-
|
316
|
-
# in webserver_monitor.rb
|
317
|
-
require 'rubix'
|
318
|
-
require 'net/http'
|
319
|
-
require 'uri'
|
320
|
-
|
321
|
-
class WebserverMonitor < Rubix::ChefMonitor
|
322
|
-
|
323
|
-
def webserver
|
324
|
-
@webserver ||= chef_node_from_node_name('my_webserver')
|
325
|
-
end
|
326
|
-
|
327
|
-
def uri
|
328
|
-
URI.parse("http://#{webserver['ec2']['public_hostname']}")
|
329
|
-
end
|
330
|
-
|
331
|
-
def measure
|
332
|
-
begin
|
333
|
-
if Net::HTTP.get_response(uri).code.to_i == 200
|
334
|
-
availability = 1
|
335
|
-
else
|
336
|
-
availability = 0
|
337
|
-
end
|
338
|
-
rescue => e
|
339
|
-
availability = 0
|
340
|
-
end
|
341
|
-
write do |data|
|
342
|
-
data << ([['webserver.available', availability]])
|
343
|
-
end
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
WebserverMonitor.run if $0 == __FILE__
|
348
|
-
|
349
|
-
To run this monitor you'll have to pass in credentials used to authenticate with Chef:
|
184
|
+
You can pipe the results directly to Zabbix (uses {Zabbix
|
185
|
+
sender}[http://www.zabbix.com/documentation/1.8/manual/processes/zabbix_sender]
|
186
|
+
behind the scenes):
|
350
187
|
|
351
|
-
$
|
188
|
+
$ ruby memory_monitor.rb --loop=30 --send
|
352
189
|
|
353
|
-
Make sure you can read the file at <tt>/etc/chef/client.pem</tt>!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.7
|
data/lib/rubix.rb
CHANGED
@@ -69,6 +69,17 @@ module Rubix
|
|
69
69
|
@connection
|
70
70
|
end
|
71
71
|
|
72
|
+
# Return the current Rubix version.
|
73
|
+
#
|
74
|
+
# @return [String]
|
75
|
+
def self.version
|
76
|
+
@version ||= begin
|
77
|
+
File.read(File.expand_path('../../VERSION', __FILE__)).chomp
|
78
|
+
rescue => e
|
79
|
+
'unknown'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
72
83
|
# Base class for Rubix errors.
|
73
84
|
Error = Class.new(RuntimeError)
|
74
85
|
|
data/lib/rubix/auto_sender.rb
CHANGED
@@ -2,27 +2,118 @@ require 'rubix/log'
|
|
2
2
|
|
3
3
|
module Rubix
|
4
4
|
|
5
|
-
#
|
5
|
+
# == Sender
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# should be written, and it can then accept data and forward it to a
|
11
|
-
# Zabbix server using the +zabbix_sender+ utility that comes with
|
12
|
-
# Zabbix.
|
7
|
+
# Rubix comes with a +zabbix_pipe+ script which, coupled with the
|
8
|
+
# {+zabbix_sender+}[http://www.zabbix.com/documentation/1.8/manpages/zabbix_sender]
|
9
|
+
# utility, allows for writing data to Zabbix.
|
13
10
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# data through the same process.
|
11
|
+
# By the design of Zabbix, all data written via +zabbix_sender+ (and
|
12
|
+
# therefore +zabbix_pipe+) must be written to items with type "Zabbix
|
13
|
+
# trapper". This type instructs Zabbix to accept values written by
|
14
|
+
# +zabbix_sender+.
|
19
15
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
16
|
+
# +zabbix_pipe+ can consume data from +STDIN+, a file on disk, or a
|
17
|
+
# {named pipe}[http://en.wikipedia.org/wiki/Named_pipe]. It consumes
|
18
|
+
# data one line at a time from any of these sources and uses the
|
19
|
+
# +zabbix_sender+ utility to send this data to a Zabbix server.
|
20
|
+
#
|
21
|
+
# Here's an example of starting +zabbix_pipe+ and sending some data onto
|
22
|
+
# Zabbix. (Credentials and addresses for the Zabbix server and the
|
23
|
+
# Zabbix API can all be customized; see the <tt>--help</tt> option.)
|
24
|
+
#
|
25
|
+
# # Send one data point -- this is tab separated!
|
26
|
+
# $ echo "foo.bar.baz 123" | zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
27
|
+
# # Send a bunch of data points in a file
|
28
|
+
# $ cat my_data.tsv | zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
29
|
+
#
|
30
|
+
# You can also pass the file directly:
|
31
|
+
#
|
32
|
+
# # Send a bunch of data points in a file
|
33
|
+
# $ zabbix_pipe --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group' my_data.tsv
|
34
|
+
#
|
35
|
+
# You can also listen from a named pipe. This is useful on a
|
36
|
+
# "production" system in which many processes may want to simply and
|
37
|
+
# easily write somewhere without worrying about what happens.
|
38
|
+
#
|
39
|
+
# # In the first terminal
|
40
|
+
# $ mkfifo /dev/zabbix
|
41
|
+
# $ zabbix_pipe --pipe=/dev/zabbix --host='My Zabbix Host' --host_groups='My Zabbix Servers,Some Other Group'
|
42
|
+
#
|
43
|
+
# # In another terminal
|
44
|
+
# $ echo "foo.bar.baz 123" > /dev/zabbix
|
45
|
+
# $ cat my_data > /dev/zabbix
|
46
|
+
#
|
47
|
+
# In any of these modes, you can also send JSON data directly.
|
48
|
+
#
|
49
|
+
# $ echo '{"data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
50
|
+
#
|
51
|
+
# This simple block of JSON doesn't really add any power to
|
52
|
+
# +zabbix_pipe+. What becomes more interesting is that we can wedge in
|
53
|
+
# data for *diffferent* hosts, items, &c. when using JSON input:
|
54
|
+
#
|
55
|
+
# $ echo '{"host": "My first host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
56
|
+
# $ echo '{"host": "My second host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
57
|
+
# $ echo '{"host": "My third host", "host_groups": "My Zabbix Servers,Some Other Group", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
58
|
+
#
|
59
|
+
# Rubix will switch hosts on the fly.
|
60
|
+
#
|
61
|
+
# === Auto-vivification
|
62
|
+
#
|
63
|
+
# By default, for every item written into +zabbix_pipe+, Rubix will
|
64
|
+
# first check, using the Zabbix API, whether an item with the given key
|
65
|
+
# exists for the given host. If not, Rubix will create the host and
|
66
|
+
# the item. You can pass a few details along with your data (when
|
67
|
+
# writing in JSON format) or at startup of the +zabbix_pipe+ to tune
|
68
|
+
# some of the properites of newly created hosts and items:
|
69
|
+
#
|
70
|
+
# $ echo '{"host": "My host", "hostgroups": "Host Group 1,Host Group 2", "templates": "Template 1,Template 2", "applications": "App 1, App2", "data": [{"key": "foo.bar.baz", "value": 123}, {"key": "foo.bar.baz", "value": 101}]}' > /dev/zabbix
|
71
|
+
#
|
72
|
+
# If the host 'My host' does not exist, Rubix will create it, putting in
|
73
|
+
# each of the host groups 'Host Group 1' and 'Host Group 2' (which will
|
74
|
+
# also be auto-vivified), and attach it to templates 'Template 1' and
|
75
|
+
# 'Template 2' (auto-vivified). If the item does not exist for the host
|
76
|
+
# 'My host', then it will be created and put inside applications 'App1'
|
77
|
+
# and 'App2' (auto-vivified). The value type of the item (unsigned int,
|
78
|
+
# float, character, text, &c.) will be chosen dynamically based on the
|
79
|
+
# value being written. The created items will all be of the type "Zabbix
|
80
|
+
# trapper" so that they can be written to.
|
81
|
+
#
|
82
|
+
# Auto-vivification is intended to make it easy to register a lot of
|
83
|
+
# dynamic hosts and items in Zabbix. This is perfect for cloud
|
84
|
+
# deployments where resources to be monitored are often dynamic.
|
85
|
+
#
|
86
|
+
# ==== Failed writes
|
87
|
+
#
|
88
|
+
# By the design of Zabbix, a newly created item of type 'Zabbix trapper'
|
89
|
+
# will not accept data for some interval, typically a minute or so,
|
90
|
+
# after being created. This means that when writing a series of values
|
91
|
+
# for some non-existent item 'foo.bar.baz', the first write will cause
|
92
|
+
# the item to be created (auto-vivified), the next several writes will
|
93
|
+
# fail as the Zabbix server is not accepting writes for this item yet,
|
94
|
+
# and then all writes will begin to succeed as the Zabbix server catches
|
95
|
+
# up. If it is absolutely essential for all writes to succeed,
|
96
|
+
# including the first, then +zabbix_pipe+ needs to go to sleep for a
|
97
|
+
# while after creating a new item in order to give the Zabbix server
|
98
|
+
# time to catch up. This can be configured with the
|
99
|
+
# <tt>--create_item_sleep</tt> option. By default this is set to 0.
|
100
|
+
#
|
101
|
+
# ==== Skipping auto-vivification
|
102
|
+
#
|
103
|
+
# Attempting to auto-vivify keys on every single write is expensive and
|
104
|
+
# does not scale. It's recommended, therefore, to run +zabbix_pipe+
|
105
|
+
# with the <tt>--fast</tt> flag in production settings. In this mode,
|
106
|
+
# +zabbix_pipe+ will not attempt to auto-vivify anything -- if items do
|
107
|
+
# not exist, writes will just fail, as they do with +zabbix_sender+
|
108
|
+
# itself.
|
109
|
+
#
|
110
|
+
# A good pattern is to set up a production pipe (in <tt>--fast</tt>)
|
111
|
+
# mode at <tt>/dev/zabbix</tt> and to do all development/deployment with
|
112
|
+
# a separate instance of +zabbix_pipe+. Once development/deployment is
|
113
|
+
# complete and all hosts, groups, templates, applications, and items
|
114
|
+
# have been created, switch to writing all data in "production mode"
|
115
|
+
# using the <tt>--fast</tt> pipe at <tt>/dev/zabbix</tt>.
|
24
116
|
class AutoSender
|
25
|
-
|
26
117
|
include Logs
|
27
118
|
|
28
119
|
# @return [Hash] settings
|
data/lib/rubix/connection.rb
CHANGED
@@ -159,6 +159,11 @@ module Rubix
|
|
159
159
|
# restarting or something like that. We keep trying until that
|
160
160
|
# doesn't happen.
|
161
161
|
#
|
162
|
+
# During long-running connections, the Zabbix server can reap the
|
163
|
+
# existing session if some time has passed since the last request
|
164
|
+
# from this Connection. This method will also refresh the
|
165
|
+
# connection in that instance.
|
166
|
+
#
|
162
167
|
# You shouldn't have to use this method directly -- the
|
163
168
|
# <tt>Rubix::Connection#authorize!</tt> and
|
164
169
|
# <tt>Rubix::Connection#request</tt> methods already use this
|
@@ -172,6 +177,9 @@ module Rubix
|
|
172
177
|
till_response(attempt + 1, max_attempts, &block)
|
173
178
|
when response.code.to_i >= 500
|
174
179
|
raise ConnectionError.new("Too many consecutive failed requests (#{max_attempts}) to the Zabbix API at (#{uri}).")
|
180
|
+
when response.code.to_i == 200 && authorized? && response.body =~ /-32602/ && response.body =~ /Not authorized/
|
181
|
+
authorize!
|
182
|
+
till_response(attempt, max_attempts, &block)
|
175
183
|
else
|
176
184
|
@last_response = response
|
177
185
|
end
|
@@ -221,6 +229,7 @@ module Rubix
|
|
221
229
|
Rubix.logger.log(Logger::DEBUG, "SEND: #{json_body}") if Rubix.logger
|
222
230
|
Net::HTTP::Post.new(uri.path).tap do |req|
|
223
231
|
req['Content-Type'] = 'application/json-rpc'
|
232
|
+
req['User-Agent'] = "Rubix v. #{Rubix.version}"
|
224
233
|
req.body = json_body
|
225
234
|
end
|
226
235
|
end
|
@@ -67,7 +67,7 @@ module Rubix
|
|
67
67
|
s.define :port, :description => "Port of a Zabbix server", :required => false, :default => 10051, :type => Integer
|
68
68
|
s.define :host, :description => "Name of a Zabbix host", :required => false, :default => ENV["HOSTNAME"]
|
69
69
|
s.define :config, :description => "Local Zabbix agentd configuration file", :required => false, :default => "/etc/zabbix/zabbix_agentd.conf"
|
70
|
-
s.define :send, :description => "Send data
|
70
|
+
s.define :send, :description => "Send data directly to Zabbix using 'zabbix_sender'", :required => false, :default => false, :type => :boolean
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -41,6 +41,12 @@ describe Rubix::Connection do
|
|
41
41
|
@connection.request_id.should == 3 # it's the number used for the *next* request
|
42
42
|
end
|
43
43
|
|
44
|
+
it "should refresh its authorization credentials if they are deleted automatically" do
|
45
|
+
@mock_response.stub!(:body).and_return('{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params.","data":"Not authorized"},"id":4}')
|
46
|
+
@connection.should_receive(:authorize!)
|
47
|
+
@connection.request('foobar', {})
|
48
|
+
end
|
49
|
+
|
44
50
|
end
|
45
51
|
|
46
52
|
describe "sending web requests" do
|
@@ -79,7 +79,7 @@ module Rubix
|
|
79
79
|
$RUBIX_MYSQL.query(%Q{INSERT INTO users_groups (usrgrpid, userid) SELECT users.userid, usrgrp.usrgrpid FROM users, usrgrp WHERE users.alias = '#{INTEGRATION_USER}' AND usrgrp.name = '#{INTEGRATION_GROUP}'})
|
80
80
|
true
|
81
81
|
rescue => e
|
82
|
-
puts "Could not create
|
82
|
+
puts "Could not create integration user or group: #{e.class} -- #{e.message}"
|
83
83
|
puts e.backtrace
|
84
84
|
false
|
85
85
|
end
|
data/spec/test.yml
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
---
|
2
|
-
|
2
|
+
|
3
3
|
api:
|
4
|
-
url:
|
5
|
-
|
6
|
-
password: zabbix
|
4
|
+
url: localhost:8080/api_jsonrpc.php
|
5
|
+
|
7
6
|
mysql:
|
8
|
-
host:
|
9
|
-
username:
|
7
|
+
host: localhost
|
8
|
+
username: dhruv
|
10
9
|
password:
|
11
|
-
database: zabbix
|
10
|
+
database: zabbix
|
11
|
+
|
metadata
CHANGED
@@ -1,194 +1,214 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubix
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.7
|
4
5
|
prerelease:
|
5
|
-
version: 0.5.6
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Dhruv Bansal
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-07-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: rspec
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :development
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: mysql2
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
25
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mysql2
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
35
38
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: json
|
39
39
|
prerelease: false
|
40
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
|
-
requirements:
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
43
51
|
- - <=
|
44
|
-
- !ruby/object:Gem::Version
|
52
|
+
- !ruby/object:Gem::Version
|
45
53
|
version: 1.6.1
|
46
54
|
type: :runtime
|
47
|
-
version_requirements: *id003
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: configliere
|
50
55
|
prerelease: false
|
51
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - <=
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.6.1
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: configliere
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
52
65
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
56
69
|
version: 0.4.8
|
57
70
|
type: :runtime
|
58
|
-
version_requirements: *id004
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: multipart-post
|
61
71
|
prerelease: false
|
62
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
73
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version:
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.4.8
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: multipart-post
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
68
86
|
type: :runtime
|
69
|
-
|
70
|
-
|
71
|
-
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Rubix provides abstractions for connecting to Zabbix's API, an ORM for
|
95
|
+
wrapping Zabbix resources, a set of scripts for writing data to Zabbix, and a collection
|
96
|
+
of Monitor classes for building periodic monitors.
|
97
|
+
email:
|
72
98
|
- dhruv@infochimps.com
|
73
|
-
executables:
|
99
|
+
executables:
|
74
100
|
- zabbix_api
|
75
101
|
- zabbix_pipe
|
76
102
|
extensions: []
|
77
|
-
|
78
103
|
extra_rdoc_files: []
|
79
|
-
|
80
|
-
files:
|
104
|
+
files:
|
81
105
|
- bin/zabbix_api
|
82
106
|
- bin/zabbix_pipe
|
83
|
-
- lib/rubix
|
84
|
-
- lib/rubix/
|
85
|
-
- lib/rubix/
|
107
|
+
- lib/rubix.rb
|
108
|
+
- lib/rubix/models/template.rb
|
109
|
+
- lib/rubix/models/trigger.rb
|
110
|
+
- lib/rubix/models/media_type.rb
|
111
|
+
- lib/rubix/models/user_macro.rb
|
112
|
+
- lib/rubix/models/action.rb
|
113
|
+
- lib/rubix/models/script.rb
|
114
|
+
- lib/rubix/models/item.rb
|
115
|
+
- lib/rubix/models/user_group.rb
|
116
|
+
- lib/rubix/models/operation.rb
|
117
|
+
- lib/rubix/models/host.rb
|
118
|
+
- lib/rubix/models/host_group.rb
|
119
|
+
- lib/rubix/models/model.rb
|
120
|
+
- lib/rubix/models/medium.rb
|
121
|
+
- lib/rubix/models/time_series.rb
|
122
|
+
- lib/rubix/models/condition.rb
|
123
|
+
- lib/rubix/models/application.rb
|
124
|
+
- lib/rubix/models/user.rb
|
125
|
+
- lib/rubix/examples/simple_zabbix_monitor.rb
|
126
|
+
- lib/rubix/examples/simple_uptime_monitor.rb
|
127
|
+
- lib/rubix/examples/simple_cluster_monitor.rb
|
128
|
+
- lib/rubix/examples/simple_chef_monitor.rb
|
129
|
+
- lib/rubix/auto_sender.rb
|
130
|
+
- lib/rubix/sender.rb
|
131
|
+
- lib/rubix/log.rb
|
132
|
+
- lib/rubix/models.rb
|
133
|
+
- lib/rubix/monitors.rb
|
134
|
+
- lib/rubix/response.rb
|
135
|
+
- lib/rubix/associations/has_many_hosts.rb
|
136
|
+
- lib/rubix/associations/has_many_applications.rb
|
86
137
|
- lib/rubix/associations/belongs_to_media_type.rb
|
87
138
|
- lib/rubix/associations/belongs_to_template.rb
|
139
|
+
- lib/rubix/associations/has_many_host_groups.rb
|
140
|
+
- lib/rubix/associations/has_many_users.rb
|
141
|
+
- lib/rubix/associations/has_many_conditions.rb
|
88
142
|
- lib/rubix/associations/belongs_to_user.rb
|
89
143
|
- lib/rubix/associations/belongs_to_user_group.rb
|
90
|
-
- lib/rubix/associations/
|
91
|
-
- lib/rubix/associations/
|
92
|
-
- lib/rubix/associations/has_many_host_groups.rb
|
93
|
-
- lib/rubix/associations/has_many_hosts.rb
|
144
|
+
- lib/rubix/associations/belongs_to_host.rb
|
145
|
+
- lib/rubix/associations/belongs_to_item.rb
|
94
146
|
- lib/rubix/associations/has_many_items.rb
|
95
147
|
- lib/rubix/associations/has_many_templates.rb
|
148
|
+
- lib/rubix/associations/belongs_to_action.rb
|
96
149
|
- lib/rubix/associations/has_many_user_groups.rb
|
97
150
|
- lib/rubix/associations/has_many_user_macros.rb
|
98
|
-
- lib/rubix/associations/has_many_users.rb
|
99
|
-
- lib/rubix/associations.rb
|
100
|
-
- lib/rubix/auto_sender.rb
|
101
|
-
- lib/rubix/connection.rb
|
102
|
-
- lib/rubix/examples/simple_chef_monitor.rb
|
103
|
-
- lib/rubix/examples/simple_cluster_monitor.rb
|
104
|
-
- lib/rubix/examples/simple_uptime_monitor.rb
|
105
|
-
- lib/rubix/examples/simple_zabbix_monitor.rb
|
106
|
-
- lib/rubix/log.rb
|
107
|
-
- lib/rubix/models/action.rb
|
108
|
-
- lib/rubix/models/application.rb
|
109
|
-
- lib/rubix/models/condition.rb
|
110
|
-
- lib/rubix/models/host.rb
|
111
|
-
- lib/rubix/models/host_group.rb
|
112
|
-
- lib/rubix/models/item.rb
|
113
|
-
- lib/rubix/models/media_type.rb
|
114
|
-
- lib/rubix/models/medium.rb
|
115
|
-
- lib/rubix/models/model.rb
|
116
|
-
- lib/rubix/models/operation.rb
|
117
|
-
- lib/rubix/models/script.rb
|
118
|
-
- lib/rubix/models/template.rb
|
119
|
-
- lib/rubix/models/time_series.rb
|
120
|
-
- lib/rubix/models/trigger.rb
|
121
|
-
- lib/rubix/models/user.rb
|
122
|
-
- lib/rubix/models/user_group.rb
|
123
|
-
- lib/rubix/models/user_macro.rb
|
124
|
-
- lib/rubix/models.rb
|
125
151
|
- lib/rubix/monitors/chef_monitor.rb
|
126
152
|
- lib/rubix/monitors/cluster_monitor.rb
|
127
|
-
- lib/rubix/monitors/monitor.rb
|
128
153
|
- lib/rubix/monitors/zabbix_monitor.rb
|
129
|
-
- lib/rubix/monitors.rb
|
130
|
-
- lib/rubix/
|
131
|
-
- lib/rubix/
|
132
|
-
-
|
133
|
-
- spec/data/test_template.xml
|
134
|
-
- spec/requests/action_request_spec.rb
|
135
|
-
- spec/requests/application_request_spec.rb
|
136
|
-
- spec/requests/connection_request_spec.rb
|
137
|
-
- spec/requests/host_group_request_spec.rb
|
138
|
-
- spec/requests/host_request_spec.rb
|
139
|
-
- spec/requests/item_request_spec.rb
|
140
|
-
- spec/requests/media_type_request_spec.rb
|
141
|
-
- spec/requests/script_request_spec.rb
|
142
|
-
- spec/requests/template_request_spec.rb
|
143
|
-
- spec/requests/time_series_request_spec.rb
|
144
|
-
- spec/requests/trigger_request_spec.rb
|
145
|
-
- spec/requests/user_group_request_spec.rb
|
146
|
-
- spec/requests/user_macro_request_spec.rb
|
147
|
-
- spec/requests/user_request_spec.rb
|
148
|
-
- spec/rubix/auto_sender_spec.rb
|
149
|
-
- spec/rubix/connection_spec.rb
|
154
|
+
- lib/rubix/monitors/monitor.rb
|
155
|
+
- lib/rubix/connection.rb
|
156
|
+
- lib/rubix/associations.rb
|
157
|
+
- spec/test.yml
|
150
158
|
- spec/rubix/model_spec.rb
|
151
|
-
- spec/rubix/
|
152
|
-
- spec/rubix/monitors/cluster_monitor_spec.rb
|
159
|
+
- spec/rubix/auto_sender_spec.rb
|
153
160
|
- spec/rubix/monitors/monitor_spec.rb
|
161
|
+
- spec/rubix/monitors/chef_monitor_spec.rb
|
154
162
|
- spec/rubix/monitors/zabbix_monitor_spec.rb
|
163
|
+
- spec/rubix/monitors/cluster_monitor_spec.rb
|
155
164
|
- spec/rubix/response_spec.rb
|
156
165
|
- spec/rubix/sender_spec.rb
|
166
|
+
- spec/rubix/connection_spec.rb
|
167
|
+
- spec/requests/time_series_request_spec.rb
|
168
|
+
- spec/requests/media_type_request_spec.rb
|
169
|
+
- spec/requests/script_request_spec.rb
|
170
|
+
- spec/requests/item_request_spec.rb
|
171
|
+
- spec/requests/action_request_spec.rb
|
172
|
+
- spec/requests/host_group_request_spec.rb
|
173
|
+
- spec/requests/user_macro_request_spec.rb
|
174
|
+
- spec/requests/connection_request_spec.rb
|
175
|
+
- spec/requests/template_request_spec.rb
|
176
|
+
- spec/requests/trigger_request_spec.rb
|
177
|
+
- spec/requests/host_request_spec.rb
|
178
|
+
- spec/requests/user_request_spec.rb
|
179
|
+
- spec/requests/user_group_request_spec.rb
|
180
|
+
- spec/requests/application_request_spec.rb
|
157
181
|
- spec/spec_helper.rb
|
158
|
-
- spec/support/configliere_helper.rb
|
159
182
|
- spec/support/integration_helper.rb
|
160
183
|
- spec/support/response_helper.rb
|
161
|
-
- spec/
|
184
|
+
- spec/support/configliere_helper.rb
|
185
|
+
- spec/data/test_template.xml
|
162
186
|
- LICENSE
|
163
187
|
- README.rdoc
|
164
188
|
- VERSION
|
165
189
|
homepage: http://github.com/dhruvbansal/rubix
|
166
190
|
licenses: []
|
167
|
-
|
168
191
|
post_install_message:
|
169
192
|
rdoc_options: []
|
170
|
-
|
171
|
-
require_paths:
|
193
|
+
require_paths:
|
172
194
|
- lib
|
173
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
174
196
|
none: false
|
175
|
-
requirements:
|
176
|
-
- -
|
177
|
-
- !ruby/object:Gem::Version
|
178
|
-
version:
|
179
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ! '>='
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
180
202
|
none: false
|
181
|
-
requirements:
|
182
|
-
- -
|
183
|
-
- !ruby/object:Gem::Version
|
184
|
-
version:
|
203
|
+
requirements:
|
204
|
+
- - ! '>='
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '0'
|
185
207
|
requirements: []
|
186
|
-
|
187
208
|
rubyforge_project:
|
188
|
-
rubygems_version: 1.8.
|
209
|
+
rubygems_version: 1.8.23
|
189
210
|
signing_key:
|
190
211
|
specification_version: 3
|
191
212
|
summary: A Ruby client for configuring and writing data to Zabbix
|
192
213
|
test_files: []
|
193
|
-
|
194
214
|
has_rdoc:
|