-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
256 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,5 +18,9 @@ def create oids | |
pdu | ||
end | ||
|
||
def self.createPDU target | ||
Snmpjr::Wrappers::PDU.new | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
require 'snmpjr/wrappers/util' | ||
require 'snmpjr/wrappers/smi' | ||
require 'snmpjr/session' | ||
|
||
class Snmpjr | ||
class Walker | ||
def initialize opts = {} | ||
@target = opts.fetch(:target) | ||
end | ||
|
||
def walk oid | ||
session = Snmpjr::Session.new | ||
session.start | ||
|
||
tree_utils = Snmpjr::Wrappers::Util::TreeUtils.new(session.snmp, pdu_factory) | ||
begin | ||
response = tree_utils.getSubtree(@target, oid) | ||
rescue Exception => e | ||
raise RuntimeError.new e.to_s | ||
ensure | ||
session.close | ||
end | ||
results = response.flat_map {|response_event| | ||
extract_variable_bindings(response_event) | ||
} | ||
results | ||
end | ||
|
||
private | ||
|
||
def extract_variable_bindings event | ||
if event.is_error? | ||
if event.error_message == 'Request timed out.' | ||
raise Snmpjr::TargetTimeoutError.new('Request timed out') | ||
else | ||
raise Snmpjr::RuntimeError.new(event.error_message) | ||
end | ||
end | ||
|
||
event.variable_bindings.flat_map {|vb| | ||
Snmpjr::Response.new(value: vb.variable.to_s) | ||
} | ||
end | ||
|
||
def pdu_factory | ||
Snmpjr::Wrappers::Util::DefaultPDUFactory.new | ||
end | ||
|
||
end | ||
end |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
require 'snmpjr/wrappers/snmp4j' | ||
|
||
class Snmpjr | ||
module Wrappers | ||
module Util | ||
include_package 'org.snmp4j.util' | ||
end | ||
end | ||
end |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
require 'snmpjr' | ||
require 'snmpjr/response' | ||
require 'snmpjr/target_timeout_error' | ||
|
||
describe "snmpjr" do | ||
|
||
describe 'WALK' do | ||
context 'when the host is reachable' do | ||
subject { Snmpjr.new(host: 'demo.snmplabs.com', port: 161, community: 'public') } | ||
|
||
it 'can perform a simple synchronous walk request on an snmp agent' do | ||
response = subject.walk '1.3.6.1.2.1.1' | ||
expect(response.count).to eq 11 | ||
expect(response.first.to_s).to eq 'SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m' | ||
expect(response.last.to_s).to match /^\d+\:\d+:\d+\.\d+$/ | ||
end | ||
|
||
context "when a non existent subtree is walked" do | ||
it 'returns an empty array' do | ||
expect(subject.walk '1.3.6.1.5').to eq [] | ||
end | ||
end | ||
end | ||
|
||
context 'when the host is unreachable' do | ||
subject { Snmpjr.new(host: 'example.com', port: 161, community: 'public', timeout: 50) } | ||
|
||
it 'the request times out after 5 seconds' do | ||
expect{ | ||
subject.walk '1.3.6.1.2.1.1' | ||
}.to raise_error(Snmpjr::TargetTimeoutError) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
require production_code | ||
|
||
describe Snmpjr::Walker do | ||
let(:target) { double :target } | ||
let(:oid) { Snmpjr::Wrappers::SMI::OID.new '1.2.3.4.5.6' } | ||
let(:session) { double(:session).as_null_object } | ||
|
||
let(:pdu_factory) { double Snmpjr::Wrappers::Util::DefaultPDUFactory } | ||
let(:tree_util) { double Snmpjr::Wrappers::Util::TreeUtils } | ||
|
||
subject { described_class.new(target: target) } | ||
|
||
let(:vb1) { Snmpjr::Wrappers::SMI::VariableBinding.new( | ||
Snmpjr::Wrappers::SMI::OID.new('1.3.6'), | ||
Snmpjr::Wrappers::SMI::OctetString.new('Sample Result 1')) | ||
} | ||
|
||
let(:vb2) { Snmpjr::Wrappers::SMI::VariableBinding.new( | ||
Snmpjr::Wrappers::SMI::OID.new('1.3.6.1'), | ||
Snmpjr::Wrappers::SMI::OctetString.new('Sample Result 2')) | ||
} | ||
let(:tree_event_1) { double :tree_event_1, {variable_bindings: [vb1], is_error?: false} } | ||
let(:tree_event_2) { double :tree_event_2, {variable_bindings: [vb2], is_error?: false} } | ||
let(:example_event_responses) { [tree_event_1, tree_event_2] } | ||
|
||
before do | ||
allow(Snmpjr::Wrappers::Util::DefaultPDUFactory).to receive(:new).and_return pdu_factory | ||
allow(Snmpjr::Session).to receive(:new).and_return session | ||
|
||
allow(Snmpjr::Wrappers::Util::TreeUtils).to receive(:new).with(session.snmp, pdu_factory).and_return tree_util | ||
allow(tree_util).to receive(:getSubtree).with(target, oid).and_return example_event_responses | ||
end | ||
|
||
describe '#walk' do | ||
it 'starts an snmp session' do | ||
expect(session).to receive(:start) | ||
subject.walk oid | ||
end | ||
|
||
context 'when an exception is raised' do | ||
before do | ||
allow(tree_util).to receive(:getSubtree).with(target, oid).and_raise Exception.new 'noAccess' | ||
end | ||
it 'raises a runtime error' do | ||
expect{ | ||
subject.walk oid | ||
}.to raise_error RuntimeError | ||
end | ||
end | ||
|
||
context 'when a target times out' do | ||
let(:tree_event_1) { double :tree_event_1 } | ||
before do | ||
allow(tree_event_1).to receive(:is_error?).and_return true | ||
allow(tree_event_1).to receive(:error_message).and_return 'Request timed out.' | ||
end | ||
|
||
it 'raises a timeout error' do | ||
expect{ | ||
subject.walk oid | ||
}.to raise_error Snmpjr::TargetTimeoutError | ||
end | ||
|
||
end | ||
|
||
context 'when a walk returns no variable bindings' do | ||
let(:tree_event) { double :tree_event, {variable_bindings: [], is_error?: false } } | ||
let(:example_event_responses) { [tree_event] } | ||
|
||
it 'returns an empty array' do | ||
expect(subject.walk oid).to eq [] | ||
end | ||
end | ||
|
||
it 'performs a synchronous walk' do | ||
expect(subject.walk oid).to match_array [Snmpjr::Response.new(value: vb1.variable.to_s), | ||
Snmpjr::Response.new(value: vb2.variable.to_s)] | ||
end | ||
|
||
it 'closes the snmp session' do | ||
expect(session).to receive(:close) | ||
subject.walk oid | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,72 @@ | ||
require production_code | ||
|
||
describe Snmpjr do | ||
let(:target) { double Snmpjr::Target } | ||
let(:community_target) { double :community_target } | ||
let(:agent_details) { { host: '127.0.0.1', port: 161, community: 'some_community', timeout: 50, retries: 50 } } | ||
|
||
subject { described_class.new(agent_details) } | ||
|
||
before do | ||
allow(Snmpjr::Target).to receive(:new).and_return target | ||
allow(target).to receive(:create).with(agent_details).and_return community_target | ||
end | ||
|
||
describe "#get" do | ||
context "when the call is synchronous" do | ||
let(:getter) { double Snmpjr::Getter } | ||
|
||
let(:target) { double Snmpjr::Target } | ||
let(:community_target) { double :community_target } | ||
let(:getter) { double Snmpjr::Getter } | ||
before do | ||
allow(Snmpjr::Getter).to receive(:new).with(target: community_target, max_oids_per_request: 20).and_return getter | ||
end | ||
|
||
before do | ||
allow(Snmpjr::Target).to receive(:new).and_return target | ||
allow(target).to receive(:create).with(agent_details).and_return community_target | ||
allow(Snmpjr::Getter).to receive(:new).with(target: community_target, max_oids_per_request: 20).and_return getter | ||
end | ||
|
||
let(:agent_details) { { host: '127.0.0.1', port: 161, community: 'some_community', timeout: 50, retries: 50 } } | ||
subject { described_class.new(agent_details.merge({max_oids_per_request: 20})) } | ||
|
||
subject { described_class.new(agent_details.merge({max_oids_per_request: 20})) } | ||
context 'when passed a single oid' do | ||
it 'performs a synchronous get' do | ||
expect(getter).to receive(:get).with('1.2.3.4.5.6') | ||
subject.get '1.2.3.4.5.6' | ||
end | ||
end | ||
|
||
context 'when passed a single oid' do | ||
it 'performs a synchronous get' do | ||
expect(getter).to receive(:get).with('1.2.3.4.5.6') | ||
subject.get '1.2.3.4.5.6' | ||
end | ||
context 'when passed multiple oids' do | ||
it 'performs a get multiple using the getter' do | ||
expect(getter).to receive(:get_multiple).with(['1.2.3.4.5.6', '6.5.4.3.2.1']) | ||
subject.get ['1.2.3.4.5.6', '6.5.4.3.2.1'] | ||
end | ||
end | ||
|
||
context 'when passed multiple oids' do | ||
it 'performs a get multiple using the getter' do | ||
expect(getter).to receive(:get_multiple).with(['1.2.3.4.5.6', '6.5.4.3.2.1']) | ||
subject.get ['1.2.3.4.5.6', '6.5.4.3.2.1'] | ||
end | ||
context 'when an invalid argument was passed in' do | ||
it 'raises an ArgumentError' do | ||
expect { | ||
subject.get({'oid_value' => '1.3.4.5.6'}) | ||
}.to raise_error ArgumentError | ||
end | ||
end | ||
end | ||
|
||
describe '#walk' do | ||
let(:walker) { double Snmpjr::Walker } | ||
let(:oid) { double :oid } | ||
|
||
before do | ||
allow(Snmpjr::Walker).to receive(:new).with(target: community_target).and_return walker | ||
allow(Snmpjr::Wrappers::SMI::OID).to receive(:new).with('1.3.6.1.1').and_return oid | ||
end | ||
context 'when a string is passed' do | ||
it 'performs a synchronous walk' do | ||
expect(walker).to receive(:walk).with(oid) | ||
subject.walk '1.3.6.1.1' | ||
end | ||
end | ||
|
||
context 'when an invalid argument was passed in' do | ||
it 'raises an ArgumentError' do | ||
expect { | ||
subject.get({'oid_value' => '1.3.4.5.6'}) | ||
}.to raise_error ArgumentError | ||
end | ||
context 'when anything else is passed in' do | ||
it 'raises an ArgumentError' do | ||
expect { | ||
subject.walk({'oid_value' => '1.3.4.5.6'}) | ||
}.to raise_error ArgumentError | ||
end | ||
end | ||
|
||
end | ||
end |