Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sugimoto hiroshi committed Nov 8, 2012
0 parents commit d7fd725
Show file tree
Hide file tree
Showing 9 changed files with 448 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in fluent-plugin-snmp.gemspec
gemspec
gem 'polling', :https => 'https://github.com/iij/polilng.git'
13 changes: 13 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2012, Internet Initiative Japan Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Fluent::Plugin::Snmp

Fluent plugin from snmp

## Installation

Add this line to your application's Gemfile:

gem 'fluent-plugin-snmp'

And then execute:

$ bundle

Or install it yourself as:

$ gem install fluent-plugin-snmp

## Usage

<source>
type snmp
tag snmp.server1
nodes name, value
host server1
community private
version 2c
mib hrStorageIndex, hrStorageDescr, hrStorageSize, hrStorageUsed
mib_modules HOST-RESOURCES-MIB
retries 0
timeout 3s
polling_time 0,10,20,30,40,50
</source>

<source>
type snmp
tag snmp.server2
nodes name, value
host server2
community private
version 2c
mib hrStorageIndex, hrStorageDescr,
hrStorageSize, hrStorageUsed
mib_modules HOST-RESOURCES-MIB
retries 0
timeout 3s
polling_time 5,15,25,35,45,55
</source>

## Copyright
Copyright (c) 2012 Internet Initiative Inc.
Apache Licence, Version 2.0
10 changes: 10 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end

task :default => :test
21 changes: 21 additions & 0 deletions fluent-plugin-snmp.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)

Gem::Specification.new do |gem|
gem.name = "fluent-plugin-snmp"
gem.version = "0.0.1"
gem.authors = ["Hiroshi Sugimoto"]
gem.email = ["h-sugimoto@iij.ad.jp"]
gem.description = %q{Input plugin to walk snmp}
gem.summary = %q{Input plugin to walk snmp}

gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.require_paths = ["lib"]

gem.add_development_dependency "fluentd"
gem.add_development_dependency "snmp"
gem.add_runtime_dependency "fluentd"
gem.add_runtime_dependency "snmp"
end
157 changes: 157 additions & 0 deletions lib/fluent/plugin/in_snmp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
require 'snmp' # http://snmplib.rubyforge.org/doc/index.html
require 'polling' # https://github.com/iij/polling.git

module Fluent
class SnmpInput < Input
Plugin.register_input('snmp', self)

# Fluent Params
# require param: tag, mib
config_param :tag, :string
config_param :mib, :string
config_param :nodes, :string, :default => nil
config_param :polling_time, :string, :default => nil
config_param :host_name, :string, :default => nil

# SNMP Lib Params
# require param: host, community
#
# Option Default Value
# --------------------------------------
# :host 'localhost'
# :port 161
# :trap_port 162
# :community 'public'
# :write_community Same as :community
# :version :SNMPv2c
# :timeout 1 (timeout units are seconds)
# :retries 5
# :transport UDPTransport
# :max_recv_bytes 8000 bytes
# :mib_dir MIB::DEFAULT_MIB_PATH
# :mib_modules SNMPv2-SMI, SNMPv2-MIB, IF-MIB, IP-MIB, TCP-MIB, UDP-MIB
# :use_IPv6 false, unless :host is formatted like an IPv6 address
config_param :host, :string
config_param :port, :integer, :default => nil
config_param :trap_port, :integer, :default => nil
config_param :community, :string
config_param :write_community, :string, :default => nil
config_param :version, :string, :default => nil # Use :SNMPv1 or :SNMPv2c
config_param :timeout, :time, :default => nil
config_param :retries, :integer, :default => nil
config_param :transport, :string, :default => nil
config_param :max_recv_bytes, :string, :default => nil
config_param :mib_dir, :string, :default => nil
config_param :mib_modules, :string, :default => nil
config_param :use_IPv6, :string, :default => nil

def initialize
super
end

def configure(conf)
super

raise ConfigError, "tag is required param" if @tag.empty?

# @mib, @mib_modules, @nodesを配列に変換
@mib = @mib.split(',').map{|str| str.strip}
raise ConfigError, "snmp: 'mib' parameter is required on snmp input" if @mib.empty?

@mib_modules = @mib_modules.split(',').map{|str| str.strip} unless @mib_modules.nil?
raise ConfigError, "snmp: 'mib_modules' parameter is required on snmp input" if !@mib_modules.nil? && @mib_modules.empty?

@nodes = @nodes.split(',').map{|str| str.strip} unless @nodes.nil?
raise ConfigError, "snmp: 'nodes' parameter is required on snmp input" if !@nodes.nil? && @nodes.empty?

@polling_time = @polling_time.split(',').map{|str| str.strip.to_i} unless @polling_time.nil?
raise ConfigError, "snmp: 'polling_time' parameter is required on snmp input" if !@polling_time.nil? && @polling_time.empty?

# snmp version
@version = @version == "1" ? :SNMPv1 : :SNMPv2c

# SNMP Libraryの初期値を設定
@snmp_init_params = {
:host => @host, #or conf["host"]
:port => @port,
:trap_port => @trap_port,
:community => @community,
:write_community => @write_community,
:version => @version,
:timeout => @timeout,
:retries => @retries,
:transport => @transport,
:max_recv_bytes => @max_recv_bytes,
:mib_dir => @mib_dir,
:mib_modules => @mib_modules,
:use_IPv6 => @use_IPv6
}
end

def starter
@starter = Thread.new do
yield
end
end

def start
starter do
@manager = SNMP::Manager.new(@snmp_init_params)
@thread = Thread.new(&method(:run))
@end_flag = false
end
end

def run
Polling::run(@polling_time,true) do
snmpwalk(@manager, @mib, @nodes)
break if @end_flag
end
rescue => ex
$log.error "run failed", :error=>ex.message
sleep(10)
retry
end

#Ctrl-cで処理を停止時に呼ばれる
def shutdown
@end_flag = true
@thread.run
@thread.join
@starter.join
@manager.close
end

private

def snmpwalk(manager, mib, nodes = nil, test = false)
manager.walk(mib) do |row|
time = Engine.now
time = time - time % 5
record = Hash.new
row.each do |vb|
if nodes.nil?
record["mib"] = vb
else
nodes.each{|param| record[param] = check_type(vb.__send__(param))}
end
Engine.emit(@tag, time, record)
return {:time => time, :record => record} if test
end
end
end

# SNMPで取得したデータの型チェック
def check_type(value)
if value =~ /^\d+(\.\d+)?$/
return value.to_f
else
return value.to_s
end
rescue => ex
$Log.error "snmp failed to check_type", :error=>ex.message
$log.warn_backtrace ex.backtrace
end

end
end
22 changes: 22 additions & 0 deletions test/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'test/unit'

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))

require 'fluent/test'

unless ENV.has_key?('VERBOSE')
nulllogger = Object.new
nulllogger.instance_eval {|obj|
def method_missing(method, *args)
# pass
end
}
$log = nulllogger
end

require 'fluent/plugin/in_snmp'

class Test::Unit::TestCase
end

80 changes: 80 additions & 0 deletions test/plugin/hoge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
require 'helper'
require 'flexmock'

class SnmpInputTest < Test::Unit::TestCase
include FlexMock::TestCase

def setup
Fluent::Test.setup
end

CONFIG = %[
tag snmp.server1
mib hrStorageIndex, hrStorageDescr, hrStorageSize, hrStorageUsed
nodes name, value
polling_time 0,10,20,30,40,50
polling_interval 60s
host localhost
community private
mib_modules HOST-RESOURCES-MIB, IF-MIB
retries 0
timeout 3s
]

def create_driver(conf=CONFIG)
Fluent::Test::InputTestDriver.new(Fluent::SnmpInput).configure(conf)
end

def test_configure
d = create_driver

# Fluent Params
assert_equal "snmp.server1", d.instance.tag
assert_equal ["hrStorageIndex","hrStorageDescr","hrStorageSize","hrStorageUsed"], d.instance.mib
assert_equal ["name","value"], d.instance.nodes
assert_equal [0,10,20,30,40,50], d.instance.polling_time
assert_equal 60, d.instance.polling_interval

# SNMP Lib Params
assert_equal "localhost", d.instance.host
assert_nil d.instance.port
assert_nil d.instance.trap_port
assert_equal "private", d.instance.community
assert_nil d.instance.write_community
assert_equal :SNMPv2c, d.instance.version
assert_equal 3, d.instance.timeout
assert_equal 0, d.instance.retries
assert_nil d.instance.transport
assert_nil d.instance.max_recv_bytes
assert_nil d.instance.mib_dir
assert_equal ["HOST-RESOURCES-MIB","IF-MIB"], d.instance.mib_modules
assert_nil d.instance.use_IPv6
end

def test_run
d = create_driver

snmp_init_params = {
:host => d.instance.host,
:port => d.instance.host,
:trap_port => d.instance.trap_port,
:community => d.instance.community,
:write_community => d.instance.write_community,
:version => d.instance.version,
:timeout => d.instance.timeout,
:retries => d.instance.retries,
:transport => d.instance.transport,
:max_recv_bytes => d.instance.max_recv_bytes,
:mib_dir => d.instance.mib_dir,
:mib_modules => d.instance.mib_modules,
:use_IPv6 => d.instance.use_IPv6
}
end

def test_check_type
d = Fluent::SnmpInput.new
hoge = d.check_type("hoge")
assert_equal "hoge",hoge
end

end
Loading

0 comments on commit d7fd725

Please sign in to comment.