Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

first commit

  • Loading branch information...
commit d7fd7255912eb3dbca901614535de22d26dc921a 0 parents
sugimoto hiroshi authored
5 Gemfile
@@ -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 LICENSE.txt
@@ -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 README.md
@@ -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 Rakefile
@@ -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 fluent-plugin-snmp.gemspec
@@ -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 lib/fluent/plugin/in_snmp.rb
@@ -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 test/helper.rb
@@ -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 test/plugin/hoge.rb
@@ -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
88 test/plugin/test_in_snmp.rb
@@ -0,0 +1,88 @@
+require 'helper'
+require 'mocha'
+require 'time'
+
+class SnmpInputTest < Test::Unit::TestCase
+
+ def setup
+ Fluent::Test.setup
+ @obj = Fluent::SnmpInput.new
+ end
+
+ CONFIG = %[
+ tag snmp.server1
+ mib hrStorageIndex, hrStorageDescr, hrStorageSize, hrStorageUsed
+ nodes name, value
+ polling_time 0,10,20,30,40,50
+ 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
+
+ # 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_check_type
+ assert_equal "test", @obj.__send__(:check_type,"test")
+ assert_equal "utrh0", @obj.__send__(:check_type,"utrh0")
+ assert_equal "sensorValue_degC", @obj.__send__(:check_type,"sensorValue_degC")
+ assert_equal "sensorValue_%RH", @obj.__send__(:check_type,"sensorValue_%RH")
+ assert_equal 12.00, @obj.__send__(:check_type,"12")
+ assert_equal 12.34, @obj.__send__(:check_type,"12.34")
+ end
+
+ def test_snmpwalk
+ d = create_driver
+ nodes = d.instance.nodes
+ mib = d.instance.mib
+
+ snmp_init_params = {
+ :host => d.instance.host,
+ :community => d.instance.community,
+ :timeout => d.instance.timeout,
+ :retries => d.instance.retries,
+ :mib_dir => d.instance.mib_dir,
+ :mib_modules => d.instance.mib_modules,
+ }
+
+ # unixtime 1356965990
+ Time.stubs(:now).returns(Time.parse "2012/12/31 23:59:50")
+ manager = SNMP::Manager.new(snmp_init_params)
+
+ data = @obj.__send__(:snmpwalk, manager, mib, nodes, true)
+ record = data[:record]
+
+ assert_equal 1356965990, data[:time]
+ assert_equal "HOST-RESOURCES-MIB::hrStorageIndex.1", record["name"]
+ assert_equal "1", record["value"]
+ end
+
+end
Please sign in to comment.
Something went wrong with that request. Please try again.