rubix 0.5.6 → 0.5.7
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/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:
|