logstash-input-zenoss 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzllZjg1YjgzZGZmZWQzNmRhMGU4ZWExZWYyMTU1NmQwOWJmMmJiZA==
5
+ data.tar.gz: !binary |-
6
+ MDhjMmQ4OWU1MTYxMzQ3MGIxMDlmN2MxMzU2ZThiNThlODFmZjQ1OA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NTFjZDljY2FjNjUzNjc3YWVlYWNiYmQyNmEzZjM4MDFhMzVmMGVjODA0OTIw
10
+ MGQ2ZTViOTA5NTI2NWJmYjcxZGJhZWRiMWNhZjBmM2MzOWVkYTM5YjBmYmNl
11
+ N2Y2ZTllYmNjYTc0ZjYwMzFlOWY1N2RjYzk1NDM4MmU0ZWUyNDE=
12
+ data.tar.gz: !binary |-
13
+ MDJjYzZhMGI1ODIyYTNmYWM2MGRiMzRjYTI4Y2RjYjI0MTFkZmJjNDIwZmYw
14
+ NWU0ZDAzYTk0ZjYxNzk3NTliNTRmNTY1Y2E0NTg2ODlkYjUyNmIzODkyNTFi
15
+ ODgwOWJmMWQxZjQwMzhkYzcxYTgwZWU2NzcyZWE4NzY3YjgwZDY=
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .bundle
4
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+ gem 'rake'
3
+ gem 'gem_publisher'
4
+ gem 'archive-tar-minitar'
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012-2014 Elasticsearch <http://www.elasticsearch.org>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ @files=[]
2
+
3
+ task :default do
4
+ system("rake -T")
5
+ end
6
+
@@ -0,0 +1,144 @@
1
+ # encoding: utf-8
2
+ require "date"
3
+ require "logstash/inputs/rabbitmq"
4
+ require "zlib"
5
+
6
+
7
+ # Read Zenoss events from the zenoss.zenevents fanout exchange.
8
+ #
9
+ class LogStash::Inputs::Zenoss < LogStash::Inputs::RabbitMQ
10
+
11
+ config_name "zenoss"
12
+ milestone 1
13
+
14
+ # Your rabbitmq server address
15
+ config :host, :validate => :string, :default => "localhost"
16
+
17
+ # Your rabbitmq username
18
+ config :user, :validate => :string, :default => "zenoss"
19
+
20
+ # Your rabbitmq password
21
+ config :password, :validate => :password, :default => "zenoss"
22
+
23
+ # The name of the exchange to bind the queue. This is analogous to the 'rabbitmq
24
+ # output' [config 'name'](../outputs/rabbitmq)
25
+ config :exchange, :validate => :string, :default => "zenoss.zenevents"
26
+
27
+ # The routing key to use. This is only valid for direct or fanout exchanges
28
+ #
29
+ # * Routing keys are ignored on topic exchanges.
30
+ # * Wildcards are not valid on direct exchanges.
31
+ config :key, :validate => :string, :default => "zenoss.zenevent.#"
32
+
33
+ # The vhost to use. If you don't know what this is, leave the default.
34
+ config :vhost, :validate => :string, :default => "/zenoss"
35
+
36
+ def register
37
+ super
38
+ require "logstash/util/zenoss"
39
+ require "bunny"
40
+ end # def register
41
+
42
+ def run(queue)
43
+ begin
44
+ zep = Org::Zenoss::Protobufs::Zep
45
+
46
+ @logger.debug("Connecting with RabbitMQ settings #{@rabbitmq_settings.inspect}")
47
+ @bunny = Bunny.new(@rabbitmq_settings)
48
+ return if terminating?
49
+ @bunny.start
50
+ @bunny.qos({:prefetch_count => @prefetch_count})
51
+
52
+ @arguments_hash = Hash[*@arguments]
53
+
54
+ @logger.debug("Setting up queue #{@name.inspect}")
55
+ @queue = @bunny.queue(@name, {
56
+ :durable => @durable,
57
+ :auto_delete => @auto_delete,
58
+ :exclusive => @exclusive,
59
+ :arguments => @arguments_hash
60
+ })
61
+
62
+ @queue.bind(@exchange, :key => @key)
63
+
64
+ @queue.subscribe({:ack => @ack}) do |data|
65
+
66
+ # Zenoss can optionally compress message payloads.
67
+ if data[:header].content_encoding == "deflate"
68
+ data[:payload] = Zlib::Inflate.inflate(data[:payload])
69
+ end
70
+
71
+ # Decode the payload into an EventSummary.
72
+ summary = zep::EventSummary.decode(data[:payload])
73
+
74
+ # This should never happen, but skip it if it does.
75
+ next unless summary.occurrence.length > 0
76
+
77
+ occurrence = summary.occurrence[0]
78
+ #timestamp = DateTime.strptime(occurrence.created_time.to_s, "%Q").to_s
79
+ timestamp = Time.at(occurrence.created_time / 1000.0)
80
+
81
+ # LogStash event properties.
82
+ event = LogStash::Event.new(
83
+ "@timestamp" => timestamp,
84
+ "type" => @type,
85
+ "host" => occurrence.actor.element_title,
86
+ "message" => occurrence.message,
87
+ )
88
+ decorate(event)
89
+
90
+ # Direct mappings from summary.
91
+ %w{uuid}.each do |property|
92
+ property_value = occurrence.send property
93
+ if !property_value.nil?
94
+ event[property] = property_value
95
+ end
96
+ end
97
+
98
+ # Direct mappings from occurrence.
99
+ %w{
100
+ fingerprint event_class event_class_key event_key event_group agent
101
+ syslog_facility nt_event_code monitor
102
+ }.each do |property|
103
+ property_value = occurrence.send property
104
+ if !property_value.nil?
105
+ event[property] = property_value
106
+ end
107
+ end
108
+
109
+ # Enum Mappings.
110
+ event["severity"] = zep::EventSeverity.constants[occurrence.severity]
111
+
112
+ if !occurrence.status.nil?
113
+ event["status"] = zep::EventStatus.constants[occurrence.status]
114
+ end
115
+
116
+ if !occurrence.syslog_priority.nil?
117
+ event["syslog_priority"] = zep::SyslogPriority.constants[
118
+ occurrence.syslog_priority]
119
+ end
120
+
121
+ # Extra Details.
122
+ if !occurrence.details.nil?
123
+ occurrence.details.each do |detail|
124
+ if detail.value.length == 1
125
+ event[detail.name] = detail.value[0]
126
+ else
127
+ event[detail.name] = detail.value
128
+ end
129
+ end
130
+ end
131
+
132
+ queue << event
133
+ end # @queue.subscribe
134
+
135
+ rescue *[Bunny::ConnectionError, Bunny::ServerDownError] => e
136
+ @logger.error("RabbitMQ connection error, will reconnect: #{e}")
137
+ # Sleep for a bit before retrying.
138
+ # TODO(sissel): Write 'backoff' method?
139
+ sleep(1)
140
+ retry
141
+ end # begin/rescue
142
+ end # def run
143
+
144
+ end # class LogStash::Inputs::Zenoss
@@ -0,0 +1,566 @@
1
+ # encoding: utf-8
2
+ require "beefcake"
3
+
4
+ # Zenoss Protocol Buffers generated by beefcake then cleaned up and
5
+ # consolidated by hand.
6
+ #
7
+ module Org
8
+ module Zenoss
9
+ module Protobufs
10
+
11
+ module Util
12
+
13
+ class TimestampRange
14
+ include Beefcake::Message
15
+
16
+ optional :start_time, :uint64, 1
17
+ optional :end_time, :uint64, 2
18
+ end
19
+
20
+ class ScheduleWindow
21
+ include Beefcake::Message
22
+
23
+ module RepeatType
24
+ NEVER = 0
25
+ DAILY = 1
26
+ EVERY_WEEKDAY = 2
27
+ WEEKLY = 3
28
+ MONTHLY = 4
29
+ FIRST_SUNDAY = 5
30
+ end
31
+
32
+ optional :uuid, :string, 1
33
+ optional :name, :string, 2
34
+ optional :enabled, :bool, 3
35
+ optional :created_time, :uint64, 4
36
+ optional :duration_seconds, :int32, 5
37
+ optional :repeat, ScheduleWindow::RepeatType, 6
38
+ end
39
+
40
+ class ScheduleWindowSet
41
+ include Beefcake::Message
42
+
43
+ repeated :windows, ScheduleWindow, 1
44
+ end
45
+
46
+ class Property
47
+ include Beefcake::Message
48
+
49
+ required :name, :string, 1
50
+ required :value, :string, 2
51
+ end
52
+
53
+ end # module Org::Zenoss::Protobufs::Util
54
+
55
+ module Model
56
+
57
+ module ModelElementType
58
+ DEVICE = 1
59
+ COMPONENT = 2
60
+ SERVICE = 3
61
+ ORGANIZER = 4
62
+ end
63
+
64
+ class Device
65
+ include Beefcake::Message
66
+
67
+ optional :uuid, :string, 1
68
+ optional :id, :string, 2
69
+ optional :title, :string, 3
70
+ end
71
+
72
+ class Component
73
+ include Beefcake::Message
74
+
75
+ optional :uuid, :string, 1
76
+ optional :id, :string, 2
77
+ optional :title, :string, 3
78
+ optional :device, Device, 4
79
+ end
80
+
81
+ class Organizer
82
+ include Beefcake::Message
83
+
84
+ optional :uuid, :string, 1
85
+ optional :title, :string, 2
86
+ optional :path, :string, 3
87
+ end
88
+
89
+ class Service
90
+ include Beefcake::Message
91
+
92
+ optional :uuid, :string, 1
93
+ optional :title, :string, 2
94
+ repeated :impacts, :string, 3
95
+ end
96
+
97
+ end # module Org::Zenoss::Protobufs::Util
98
+
99
+ module Zep
100
+
101
+ module EventSeverity
102
+ SEVERITY_CLEAR = 0
103
+ SEVERITY_DEBUG = 1
104
+ SEVERITY_INFO = 2
105
+ SEVERITY_WARNING = 3
106
+ SEVERITY_ERROR = 4
107
+ SEVERITY_CRITICAL = 5
108
+ end
109
+
110
+ module SyslogPriority
111
+ SYSLOG_PRIORITY_EMERG = 0
112
+ SYSLOG_PRIORITY_ALERT = 1
113
+ SYSLOG_PRIORITY_CRIT = 2
114
+ SYSLOG_PRIORITY_ERR = 3
115
+ SYSLOG_PRIORITY_WARNING= 4
116
+ SYSLOG_PRIORITY_NOTICE = 5
117
+ SYSLOG_PRIORITY_INFO = 6
118
+ SYSLOG_PRIORITY_DEBUG = 7
119
+ end
120
+
121
+ module EventStatus
122
+ STATUS_NEW = 0
123
+ STATUS_ACKNOWLEDGED = 1
124
+ STATUS_SUPPRESSED = 2
125
+ STATUS_CLOSED = 3
126
+ STATUS_CLEARED = 4
127
+ STATUS_DROPPED = 5
128
+ STATUS_AGED = 6
129
+ end
130
+
131
+ module FilterOperator
132
+ OR = 1
133
+ AND = 2
134
+ end
135
+
136
+ module RuleType
137
+ RULE_TYPE_JYTHON = 1
138
+ end
139
+
140
+ class EventActor
141
+ include Beefcake::Message
142
+
143
+ optional :element_type_id, Org::Zenoss::Protobufs::Model::ModelElementType, 1
144
+ optional :element_uuid, :string, 2
145
+ optional :element_identifier, :string, 3
146
+ optional :element_title, :string, 4
147
+ optional :element_sub_type_id, Org::Zenoss::Protobufs::Model::ModelElementType, 5
148
+ optional :element_sub_uuid, :string, 6
149
+ optional :element_sub_identifier, :string, 7
150
+ optional :element_sub_title, :string, 8
151
+ end
152
+
153
+ class EventDetail
154
+ include Beefcake::Message
155
+
156
+ module EventDetailMergeBehavior
157
+ REPLACE = 1
158
+ APPEND = 2
159
+ UNIQUE = 3
160
+ end
161
+
162
+ required :name, :string, 1
163
+ repeated :value, :string, 2
164
+ optional :merge_behavior, EventDetail::EventDetailMergeBehavior, 3, :default => EventDetail::EventDetailMergeBehavior::REPLACE
165
+ end
166
+
167
+ class EventDetailSet
168
+ include Beefcake::Message
169
+
170
+ repeated :details, EventDetail, 1
171
+ end
172
+
173
+ class EventTag
174
+ include Beefcake::Message
175
+
176
+ required :type, :string, 1
177
+ repeated :uuid, :string, 2
178
+ end
179
+
180
+ class EventNote
181
+ include Beefcake::Message
182
+
183
+ optional :uuid, :string, 1
184
+ optional :user_uuid, :string, 2
185
+ optional :user_name, :string, 3
186
+ optional :created_time, :uint64, 4
187
+ required :message, :string, 5
188
+ end
189
+
190
+ class Event
191
+ include Beefcake::Message
192
+
193
+ optional :uuid, :string, 1
194
+ optional :created_time, :uint64, 2
195
+ optional :fingerprint, :string, 3
196
+ optional :event_class, :string, 4
197
+ optional :event_class_key, :string, 5
198
+ optional :event_class_mapping_uuid, :string, 6
199
+ optional :actor, EventActor, 7
200
+ optional :summary, :string, 8
201
+ optional :message, :string, 9
202
+ optional :severity, EventSeverity, 10, :default => EventSeverity::SEVERITY_INFO
203
+ optional :event_key, :string, 12
204
+ optional :event_group, :string, 13
205
+ optional :agent, :string, 14
206
+ optional :syslog_priority, SyslogPriority, 15
207
+ optional :syslog_facility, :uint32, 16
208
+ optional :nt_event_code, :uint32, 17
209
+ optional :monitor, :string, 18
210
+ repeated :details, EventDetail, 19
211
+ repeated :tags, EventTag, 20
212
+ optional :summary_uuid, :string, 21
213
+ optional :status, EventStatus, 22, :default => EventStatus::STATUS_NEW
214
+ optional :apply_transforms, :bool, 23, :default => true
215
+ optional :count, :uint32, 24, :default => 1
216
+ optional :first_seen_time, :uint64, 25
217
+ end
218
+
219
+ class ZepRawEvent
220
+ include Beefcake::Message
221
+
222
+ required :event, Event, 1
223
+ repeated :clear_event_class, :string, 2
224
+ end
225
+
226
+ class EventAuditLog
227
+ include Beefcake::Message
228
+
229
+ required :timestamp, :uint64, 1
230
+ required :new_status, EventStatus, 2
231
+ optional :user_uuid, :string, 3
232
+ optional :user_name, :string, 4
233
+ end
234
+
235
+ class EventSummary
236
+ include Beefcake::Message
237
+
238
+ optional :uuid, :string, 1
239
+ repeated :occurrence, Event, 2
240
+ optional :status, EventStatus, 3, :default => EventStatus::STATUS_NEW
241
+ optional :first_seen_time, :uint64, 4
242
+ optional :status_change_time, :uint64, 5
243
+ optional :last_seen_time, :uint64, 6
244
+ optional :count, :uint32, 7, :default => 1
245
+ optional :current_user_uuid, :string, 8
246
+ optional :current_user_name, :string, 9
247
+ optional :cleared_by_event_uuid, :string, 10
248
+ repeated :notes, EventNote, 11
249
+ repeated :audit_log, EventAuditLog, 12
250
+ optional :update_time, :uint64, 13
251
+ end
252
+
253
+ class NumberRange
254
+ include Beefcake::Message
255
+
256
+ optional :from, :sint64, 1
257
+ optional :to, :sint64, 2
258
+ end
259
+
260
+ class EventTagFilter
261
+ include Beefcake::Message
262
+
263
+ optional :op, FilterOperator, 1, :default => FilterOperator::OR
264
+ repeated :tag_uuids, :string, 2
265
+ end
266
+
267
+ class EventDetailFilter
268
+ include Beefcake::Message
269
+
270
+ required :key, :string, 1
271
+ repeated :value, :string, 2
272
+ optional :op, FilterOperator, 3, :default => FilterOperator::OR
273
+ end
274
+
275
+ class EventFilter
276
+ include Beefcake::Message
277
+
278
+ repeated :severity, EventSeverity, 1
279
+ repeated :status, EventStatus, 2
280
+ repeated :event_class, :string, 3
281
+ repeated :first_seen, :'org::zenoss::protobufs::util::TimestampRange', 4
282
+ repeated :last_seen, :'org::zenoss::protobufs::util::TimestampRange', 5
283
+ repeated :status_change, :'org::zenoss::protobufs::util::TimestampRange', 6
284
+ repeated :update_time, :'org::zenoss::protobufs::util::TimestampRange', 7
285
+ repeated :count_range, NumberRange, 8
286
+ repeated :element_identifier, :string, 9
287
+ repeated :element_sub_identifier, :string, 10
288
+ repeated :uuid, :string, 11
289
+ repeated :event_summary, :string, 12
290
+ repeated :current_user_name, :string, 13
291
+ repeated :tag_filter, EventTagFilter, 14
292
+ repeated :details, EventDetailFilter, 15
293
+ repeated :fingerprint, :string, 16
294
+ repeated :agent, :string, 17
295
+ repeated :monitor, :string, 18
296
+ optional :operator, FilterOperator, 19, :default => FilterOperator::AND
297
+ repeated :subfilter, EventFilter, 20
298
+ repeated :element_title, :string, 21
299
+ repeated :element_sub_title, :string, 22
300
+ repeated :event_key, :string, 23
301
+ repeated :event_class_key, :string, 24
302
+ repeated :event_group, :string, 25
303
+ repeated :message, :string, 26
304
+ end
305
+
306
+ class EventSort
307
+ include Beefcake::Message
308
+
309
+ module Field
310
+ SEVERITY = 1
311
+ STATUS = 2
312
+ EVENT_CLASS = 3
313
+ FIRST_SEEN = 4
314
+ LAST_SEEN = 5
315
+ STATUS_CHANGE = 6
316
+ COUNT = 7
317
+ ELEMENT_IDENTIFIER = 8
318
+ ELEMENT_SUB_IDENTIFIER = 9
319
+ EVENT_SUMMARY = 10
320
+ UPDATE_TIME = 11
321
+ CURRENT_USER_NAME = 12
322
+ AGENT = 13
323
+ MONITOR = 14
324
+ UUID = 15
325
+ FINGERPRINT = 16
326
+ DETAIL = 17
327
+ ELEMENT_TITLE = 18
328
+ ELEMENT_SUB_TITLE = 19
329
+ EVENT_KEY = 20
330
+ EVENT_CLASS_KEY = 21
331
+ EVENT_GROUP = 22
332
+ end
333
+
334
+ module Direction
335
+ ASCENDING = 1
336
+ DESCENDING = 2
337
+ end
338
+
339
+ required :field, EventSort::Field, 1
340
+ optional :direction, EventSort::Direction, 2, :default => EventSort::Direction::ASCENDING
341
+ optional :detail_key, :string, 3
342
+ end
343
+
344
+ class EventSummaryRequest
345
+ include Beefcake::Message
346
+
347
+ optional :event_filter, EventFilter, 1
348
+ optional :exclusion_filter, EventFilter, 2
349
+ repeated :sort, EventSort, 3
350
+ optional :limit, :uint32, 4, :default => 1000
351
+ optional :offset, :uint32, 5
352
+ end
353
+
354
+ class EventSummaryResult
355
+ include Beefcake::Message
356
+
357
+ repeated :events, EventSummary, 1
358
+ optional :limit, :uint32, 2
359
+ optional :next_offset, :uint32, 3
360
+ optional :total, :uint32, 4
361
+ end
362
+
363
+ class EventSummaryUpdate
364
+ include Beefcake::Message
365
+
366
+ optional :status, EventStatus, 1
367
+ optional :current_user_uuid, :string, 2
368
+ optional :current_user_name, :string, 3
369
+ end
370
+
371
+ class EventQuery
372
+ include Beefcake::Message
373
+
374
+ optional :event_filter, EventFilter, 1
375
+ optional :exclusion_filter, EventFilter, 2
376
+ repeated :sort, EventSort, 3
377
+ optional :timeout, :uint32, 4, :default => 60
378
+ end
379
+
380
+ class EventSummaryUpdateRequest
381
+ include Beefcake::Message
382
+
383
+ optional :event_query_uuid, :string, 1
384
+ required :update_fields, EventSummaryUpdate, 2
385
+ optional :offset, :uint32, 3, :default => 0
386
+ optional :limit, :uint32, 4, :default => 100
387
+ end
388
+
389
+ class EventSummaryUpdateResponse
390
+ include Beefcake::Message
391
+
392
+ optional :next_request, EventSummaryUpdateRequest, 1
393
+ optional :total, :uint32, 2
394
+ required :updated, :uint32, 3
395
+ end
396
+
397
+ class EventDetailItem
398
+ include Beefcake::Message
399
+
400
+ module EventDetailType
401
+ STRING = 1
402
+ INTEGER = 2
403
+ FLOAT = 3
404
+ LONG = 4
405
+ DOUBLE = 5
406
+ IP_ADDRESS = 6
407
+ PATH = 7
408
+ end
409
+
410
+ required :key, :string, 1
411
+ optional :type, EventDetailItem::EventDetailType, 2, :default => EventDetailItem::EventDetailType::STRING
412
+ optional :name, :string, 3
413
+ end
414
+
415
+ class EventDetailItemSet
416
+ include Beefcake::Message
417
+
418
+ repeated :details, EventDetailItem, 1
419
+ end
420
+
421
+ class Rule
422
+ include Beefcake::Message
423
+
424
+ required :api_version, :int32, 1
425
+ required :type, RuleType, 2
426
+ required :source, :string, 3
427
+ end
428
+
429
+ class EventTriggerSubscription
430
+ include Beefcake::Message
431
+
432
+ optional :uuid, :string, 1
433
+ optional :delay_seconds, :int32, 2
434
+ optional :repeat_seconds, :int32, 3
435
+ optional :send_initial_occurrence, :bool, 4, :default => true
436
+ required :subscriber_uuid, :string, 5
437
+ required :trigger_uuid, :string, 6
438
+ end
439
+
440
+ class EventTriggerSubscriptionSet
441
+ include Beefcake::Message
442
+
443
+ repeated :subscriptions, EventTriggerSubscription, 1
444
+ end
445
+
446
+ class EventTrigger
447
+ include Beefcake::Message
448
+
449
+ optional :uuid, :string, 1
450
+ optional :name, :string, 2
451
+ optional :enabled, :bool, 3, :default => true
452
+ required :rule, Rule, 4
453
+ repeated :subscriptions, EventTriggerSubscription, 5
454
+ end
455
+
456
+ class EventTriggerSet
457
+ include Beefcake::Message
458
+
459
+ repeated :triggers, EventTrigger, 1
460
+ end
461
+
462
+ class Signal
463
+ include Beefcake::Message
464
+
465
+ required :uuid, :string, 1
466
+ required :created_time, :uint64, 2
467
+ required :trigger_uuid, :string, 3
468
+ required :subscriber_uuid, :string, 4
469
+ optional :clear, :bool, 5, :default => false
470
+ optional :event, EventSummary, 6
471
+ optional :clear_event, EventSummary, 7
472
+ optional :message, :string, 8
473
+ end
474
+
475
+ class EventTagSeverity
476
+ include Beefcake::Message
477
+
478
+ required :severity, EventSeverity, 1
479
+ optional :count, :uint32, 2, :default => 0
480
+ optional :acknowledged_count, :uint32, 3, :default => 0
481
+ end
482
+
483
+ class EventTagSeverities
484
+ include Beefcake::Message
485
+
486
+ required :tag_uuid, :string, 1
487
+ repeated :severities, EventTagSeverity, 2
488
+ optional :total, :uint32, 3
489
+ end
490
+
491
+ class EventTagSeveritiesSet
492
+ include Beefcake::Message
493
+
494
+ repeated :severities, EventTagSeverities, 1
495
+ end
496
+
497
+ class ZepConfig
498
+ include Beefcake::Message
499
+
500
+ optional :event_age_disable_severity, EventSeverity, 1, :default => EventSeverity::SEVERITY_ERROR
501
+ optional :event_age_interval_minutes, :uint32, 2, :default => 240
502
+ optional :event_archive_interval_minutes, :uint32, 3, :default => 4320
503
+ optional :event_archive_purge_interval_days, :uint32, 4, :default => 90
504
+ optional :event_time_purge_interval_days, :uint32, 5, :default => 1
505
+ optional :event_age_severity_inclusive, :bool, 6, :default => false
506
+ optional :event_max_size_bytes, :uint64, 7, :default => 32768
507
+ optional :index_summary_interval_milliseconds, :uint64, 8, :default => 1000
508
+ optional :index_archive_interval_milliseconds, :uint64, 9, :default => 30000
509
+ optional :index_limit, :uint32, 10, :default => 1000
510
+ optional :aging_limit, :uint32, 11, :default => 1000
511
+ optional :archive_limit, :uint32, 12, :default => 1000
512
+ optional :aging_interval_milliseconds, :uint64, 13, :default => 60000
513
+ optional :archive_interval_milliseconds, :uint64, 14, :default => 60000
514
+ end
515
+
516
+ class DaemonHeartbeat
517
+ include Beefcake::Message
518
+
519
+ required :monitor, :string, 1
520
+ required :daemon, :string, 2
521
+ required :timeout_seconds, :uint32, 3
522
+ optional :last_time, :uint64, 4
523
+ end
524
+
525
+ class DaemonHeartbeatSet
526
+ include Beefcake::Message
527
+
528
+ repeated :heartbeats, DaemonHeartbeat, 1
529
+ end
530
+
531
+ class EventTime
532
+ include Beefcake::Message
533
+
534
+ optional :summary_uuid, :string, 1
535
+ optional :processed_time, :uint64, 2
536
+ optional :created_time, :uint64, 3
537
+ optional :first_seen_time, :uint64, 4
538
+ end
539
+
540
+ class EventTimeSet
541
+ include Beefcake::Message
542
+
543
+ repeated :event_times, EventTime, 1
544
+ end
545
+
546
+ class ZepStatistic
547
+ include Beefcake::Message
548
+
549
+ required :name, :string, 1
550
+ required :description, :string, 2
551
+ required :value, :int64, 3
552
+ end
553
+
554
+ class ZepStatistics
555
+ include Beefcake::Message
556
+
557
+ repeated :stats, ZepStatistic, 1
558
+ end
559
+
560
+ end # module Org::Zenoss:Protobufs::Zep
561
+
562
+ end # module Org::Zenoss::Protobufs
563
+
564
+ end # module Org::Zenoss
565
+
566
+ end # module Org
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = 'logstash-input-zenoss'
4
+ s.version = '0.1.0'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "Read Zenoss events from the zenoss.zenevents fanout exchange."
7
+ s.description = "Read Zenoss events from the zenoss.zenevents fanout exchange."
8
+ s.authors = ["Elasticsearch"]
9
+ s.email = 'richard.pijnenburg@elasticsearch.com'
10
+ s.homepage = "http://logstash.net/"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
15
+
16
+ # Tests
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+
19
+ # Special flag to let us know this is actually a logstash plugin
20
+ s.metadata = { "logstash_plugin" => "true", "group" => "input" }
21
+
22
+ # Gem dependencies
23
+ s.add_runtime_dependency 'logstash', '>= 1.4.0', '< 2.0.0'
24
+
25
+ s.add_runtime_dependency 'beefcake'
26
+ s.add_runtime_dependency 'logstash-input-rabbitmq'
27
+ s.add_runtime_dependency 'bunny'
28
+
29
+ end
30
+
@@ -0,0 +1,9 @@
1
+ require "gem_publisher"
2
+
3
+ desc "Publish gem to RubyGems.org"
4
+ task :publish_gem do |t|
5
+ gem_file = Dir.glob(File.expand_path('../*.gemspec',File.dirname(__FILE__))).first
6
+ gem = GemPublisher.publish_if_updated(gem_file, :rubygems)
7
+ puts "Published #{gem}" if gem
8
+ end
9
+
@@ -0,0 +1,169 @@
1
+ require "net/http"
2
+ require "uri"
3
+ require "digest/sha1"
4
+
5
+ def vendor(*args)
6
+ return File.join("vendor", *args)
7
+ end
8
+
9
+ directory "vendor/" => ["vendor"] do |task, args|
10
+ mkdir task.name
11
+ end
12
+
13
+ def fetch(url, sha1, output)
14
+
15
+ puts "Downloading #{url}"
16
+ actual_sha1 = download(url, output)
17
+
18
+ if actual_sha1 != sha1
19
+ fail "SHA1 does not match (expected '#{sha1}' but got '#{actual_sha1}')"
20
+ end
21
+ end # def fetch
22
+
23
+ def file_fetch(url, sha1)
24
+ filename = File.basename( URI(url).path )
25
+ output = "vendor/#{filename}"
26
+ task output => [ "vendor/" ] do
27
+ begin
28
+ actual_sha1 = file_sha1(output)
29
+ if actual_sha1 != sha1
30
+ fetch(url, sha1, output)
31
+ end
32
+ rescue Errno::ENOENT
33
+ fetch(url, sha1, output)
34
+ end
35
+ end.invoke
36
+
37
+ return output
38
+ end
39
+
40
+ def file_sha1(path)
41
+ digest = Digest::SHA1.new
42
+ fd = File.new(path, "r")
43
+ while true
44
+ begin
45
+ digest << fd.sysread(16384)
46
+ rescue EOFError
47
+ break
48
+ end
49
+ end
50
+ return digest.hexdigest
51
+ ensure
52
+ fd.close if fd
53
+ end
54
+
55
+ def download(url, output)
56
+ uri = URI(url)
57
+ digest = Digest::SHA1.new
58
+ tmp = "#{output}.tmp"
59
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == "https")) do |http|
60
+ request = Net::HTTP::Get.new(uri.path)
61
+ http.request(request) do |response|
62
+ fail "HTTP fetch failed for #{url}. #{response}" if [200, 301].include?(response.code)
63
+ size = (response["content-length"].to_i || -1).to_f
64
+ count = 0
65
+ File.open(tmp, "w") do |fd|
66
+ response.read_body do |chunk|
67
+ fd.write(chunk)
68
+ digest << chunk
69
+ if size > 0 && $stdout.tty?
70
+ count += chunk.bytesize
71
+ $stdout.write(sprintf("\r%0.2f%%", count/size * 100))
72
+ end
73
+ end
74
+ end
75
+ $stdout.write("\r \r") if $stdout.tty?
76
+ end
77
+ end
78
+
79
+ File.rename(tmp, output)
80
+
81
+ return digest.hexdigest
82
+ rescue SocketError => e
83
+ puts "Failure while downloading #{url}: #{e}"
84
+ raise
85
+ ensure
86
+ File.unlink(tmp) if File.exist?(tmp)
87
+ end # def download
88
+
89
+ def untar(tarball, &block)
90
+ require "archive/tar/minitar"
91
+ tgz = Zlib::GzipReader.new(File.open(tarball))
92
+ # Pull out typesdb
93
+ tar = Archive::Tar::Minitar::Input.open(tgz)
94
+ tar.each do |entry|
95
+ path = block.call(entry)
96
+ next if path.nil?
97
+ parent = File.dirname(path)
98
+
99
+ mkdir_p parent unless File.directory?(parent)
100
+
101
+ # Skip this file if the output file is the same size
102
+ if entry.directory?
103
+ mkdir path unless File.directory?(path)
104
+ else
105
+ entry_mode = entry.instance_eval { @mode } & 0777
106
+ if File.exists?(path)
107
+ stat = File.stat(path)
108
+ # TODO(sissel): Submit a patch to archive-tar-minitar upstream to
109
+ # expose headers in the entry.
110
+ entry_size = entry.instance_eval { @size }
111
+ # If file sizes are same, skip writing.
112
+ next if stat.size == entry_size && (stat.mode & 0777) == entry_mode
113
+ end
114
+ puts "Extracting #{entry.full_name} from #{tarball} #{entry_mode.to_s(8)}"
115
+ File.open(path, "w") do |fd|
116
+ # eof? check lets us skip empty files. Necessary because the API provided by
117
+ # Archive::Tar::Minitar::Reader::EntryStream only mostly acts like an
118
+ # IO object. Something about empty files in this EntryStream causes
119
+ # IO.copy_stream to throw "can't convert nil into String" on JRuby
120
+ # TODO(sissel): File a bug about this.
121
+ while !entry.eof?
122
+ chunk = entry.read(16384)
123
+ fd.write(chunk)
124
+ end
125
+ #IO.copy_stream(entry, fd)
126
+ end
127
+ File.chmod(entry_mode, path)
128
+ end
129
+ end
130
+ tar.close
131
+ File.unlink(tarball) if File.file?(tarball)
132
+ end # def untar
133
+
134
+ def ungz(file)
135
+
136
+ outpath = file.gsub('.gz', '')
137
+ tgz = Zlib::GzipReader.new(File.open(file))
138
+ begin
139
+ File.open(outpath, "w") do |out|
140
+ IO::copy_stream(tgz, out)
141
+ end
142
+ File.unlink(file)
143
+ rescue
144
+ File.unlink(outpath) if File.file?(outpath)
145
+ raise
146
+ end
147
+ tgz.close
148
+ end
149
+
150
+ desc "Process any vendor files required for this plugin"
151
+ task "vendor" do |task, args|
152
+
153
+ @files.each do |file|
154
+ download = file_fetch(file['url'], file['sha1'])
155
+ if download =~ /.tar.gz/
156
+ prefix = download.gsub('.tar.gz', '').gsub('vendor/', '')
157
+ untar(download) do |entry|
158
+ if !file['files'].nil?
159
+ next unless file['files'].include?(entry.full_name.gsub(prefix, ''))
160
+ out = entry.full_name.split("/").last
161
+ end
162
+ File.join('vendor', out)
163
+ end
164
+ elsif download =~ /.gz/
165
+ ungz(download)
166
+ end
167
+ end
168
+
169
+ end
@@ -0,0 +1 @@
1
+ require 'spec_helper'
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-input-zenoss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Elasticsearch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.0
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.0
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: beefcake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: logstash-input-rabbitmq
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bunny
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description: Read Zenoss events from the zenoss.zenevents fanout exchange.
76
+ email: richard.pijnenburg@elasticsearch.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - .gitignore
82
+ - Gemfile
83
+ - LICENSE
84
+ - Rakefile
85
+ - lib/logstash/inputs/zenoss.rb
86
+ - lib/logstash/util/zenoss.rb
87
+ - logstash-input-zenoss.gemspec
88
+ - rakelib/publish.rake
89
+ - rakelib/vendor.rake
90
+ - spec/inputs/zenoss_spec.rb
91
+ homepage: http://logstash.net/
92
+ licenses:
93
+ - Apache License (2.0)
94
+ metadata:
95
+ logstash_plugin: 'true'
96
+ group: input
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Read Zenoss events from the zenoss.zenevents fanout exchange.
117
+ test_files:
118
+ - spec/inputs/zenoss_spec.rb