Class: EventMachine::SnmpAgent::Agent

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/snmpagent/agent.rb

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Agent

Returns a new instance of Agent.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/snmpagent/agent.rb', line 66

def initialize args={}
	@host = args[:host] || "0.0.0.0"
	@port = args[:port] || 161
	@community = args[:community] || "public"
	@effective_user = args[:effective_user] # default nil
	@verbose = args[:verbose] || false

	r = (args[:recalculate_interval] || 15).to_i
	if (r > 0)
		add_hook proc {EventMachine.add_periodic_timer(r) {self.recalculate_values } }
	end

	@miblist = MibList.new
	@mibclasses = []

	mibs = args[:mib] || []
	mibs = [mibs] unless mibs.respond_to?(:each)
	mibs.each {|mib|
		# classes are modules, but modules aren't classes.
		# If we get a class, we EXPECT it to be a subclass of
		# EventMachine::SnmpAgent::Mib. We *instantiate* the
		# class, and call its methods for each individual OID
		# processor that is defined as taking a symbol.
		# If we get a Module, extend ourself with it.
		# The module will be expected to make add_object calls.
		if mib.respond_to?(:new)
			m = mib.new
			@mibclasses << m
			this = self
			mib.instance_eval {
				(@my_user_defined_oids ||= []).each {|oid,processor|
					pr = if processor.is_a?(Symbol)
						 proc {m.send processor}
					else
						processor
					end
					this.add_object oid, pr
				}
			}
		else
			self.extend mib
		end
	}
end

Instance Method Details

#add_hook(hookproc) ⇒ Object



120
121
122
123
# File 'lib/snmpagent/agent.rb', line 120

def add_hook hookproc
	@hooks ||= []
	@hooks << hookproc
end

#process_request(req_type, community, variables = []) ⇒ Object

– return an openstruct to indicate the results of the operation. DO NOT set that error_status member of the output struct unless we can actually interpret the request. A protocol-handler should deal with such a case by ignoring the request.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/snmpagent/agent.rb', line 145

def process_request req_type, community, variables = []

	@verbose and $>.puts "Received #{req_type} for #{variables.map {|v| v.first}.join(",")}"

	os = OpenStruct.new
	return os unless community == @community

	case req_type
	when :get_request
		os.error_status = 0 # SNMP noError
		variables.each_with_index {|v, ix|
			if hndlr = get_object(v.first)
				os.variables ||= []
				#value = hndlr.respond_to?(:call) ? hndlr.call : hndlr
				os.variables << [v.first, hndlr]
				@verbose and $>.puts "Fulfilled #{v.first.join(".")}::=#{hndlr.inspect}"
			else
				os.variables = nil
				os.error_status = 2 # SNMP noSuchName
				os.error_index = ix
				break
			end
		}
	when :get_next_request
		os.error_status = 0 # SNMP noError
		variables.each_with_index {|v, ix|
			oid,handler = get_next_object(v.first)
			if oid
				os.variables ||= []
				#value = handler.respond_to?(:call) ? handler.call : handler
				@verbose and $>.puts "Fulfilled #{oid.join(".")}::=#{handler.inspect}"
				os.variables << [oid, handler]
			else
				os.variables = nil
				os.error_status = 2 # SNMP noSuchName
				os.error_index = ix
				break
			end
		}
	end
	os
end

#recalculate_valuesObject

This is called on an EventMachine periodic timer, installed as a hook if the caller specifies it. It will call the #recalculate_values method of each user-defined MIB class. Default value is every fifteen seconds. User code can disable the hook altogether by specifying a :recalculate_interval of 0.



116
117
118
# File 'lib/snmpagent/agent.rb', line 116

def recalculate_values
	@mibclasses.each {|m| m.recalculate_values}
end

#runObject



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/snmpagent/agent.rb', line 125

def run
	EventMachine.run {
		EventMachine.open_datagram_socket(@host, @port, ProtocolHandler) {|c|
			c.set_handler self # probably could have a used a delegate
		}
		if @effective_user
			EventMachine.set_effective_user @effective_user
		end
		@hooks and @hooks.each {|h| h.call}
		if @verbose
			EventMachine.add_periodic_timer(60) {$>.puts "bayshore-snmp-agent #{Time.now}"}
		end
	}
end