1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21%%---------------------------------------------------------------------- 22%% This module implements an SNMP manager used in the test suite 23%%---------------------------------------------------------------------- 24%% 25 26-module(snmp_test_manager). 27 28-behaviour(gen_server). 29-behaviour(snmpm_user). 30 31 32%% External exports 33-export([ 34 start_link/0, start_link/1, 35 stop/0, 36 37 sync_get/1, sync_get/2, 38 sync_get_next/1, sync_get_next/2, 39 sync_get_bulk/3, 40 sync_set/1, sync_set/2 41 ]). 42 43 44%% Manager callback API: 45-export([ 46 handle_error/3, 47 handle_agent/5, 48 handle_pdu/4, 49 handle_trap/3, 50 handle_inform/3, 51 handle_report/3, 52 handle_invalid_result/3 53 ]). 54 55 56%% gen_server callbacks 57-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 58 code_change/3, terminate/2]). 59 60-record(state, {parent, req, agent_target_name}). 61 62-define(SERVER, ?MODULE). 63-define(USER, ?MODULE). 64 65 66%%%------------------------------------------------------------------- 67%%% API 68%%%------------------------------------------------------------------- 69 70start_link() -> 71 start_link([]). 72 73start_link(Opts) -> 74 gen_server:start_link({local, ?SERVER}, ?MODULE, [self(), Opts], []). 75 76stop() -> 77 call(stop). 78 79 80sync_get(Oids) -> 81 sync_get(Oids, fun(X) -> {ok, X} end). 82 83sync_get(Oids, Verify) when is_list(Oids) and is_function(Verify) -> 84 Verify(call({sync_get, Oids})). 85 86 87sync_get_next(Oids) -> 88 sync_get_next(Oids, fun(X) -> {ok, X} end). 89 90sync_get_next(Oids, Verify) when is_list(Oids) and is_function(Verify) -> 91 Verify(call({sync_get_next, Oids})). 92 93 94sync_get_bulk(NR, MR, Oids) -> 95 sync_get_bulk(NR, MR, Oids, fun(X) -> {ok, X} end). 96 97sync_get_bulk(NR, MR, Oids, Verify) 98 when is_integer(NR) and is_integer(MR) and 99 is_list(Oids) and is_function(Verify) -> 100 Verify(call({sync_get_bulk, NR, MR, Oids})). 101 102 103sync_set(VarsAndVals) -> 104 sync_set(VarsAndVals, fun(X) -> {ok, X} end). 105 106sync_set(VarsAndVals, Verify) 107 when is_list(VarsAndVals) and is_function(Verify) -> 108 Verify(call({sync_set, VarsAndVals})). 109 110 111%%%------------------------------------------------------------------- 112%%% Callback functions from gen_server 113%%%------------------------------------------------------------------- 114 115%%-------------------------------------------------------------------- 116%% Func: init/1 117%% Returns: {ok, State} | 118%% {ok, State, Timeout} | 119%% ignore | 120%% {stop, Reason} 121%%-------------------------------------------------------------------- 122init([Parent, Opts]) -> 123 process_flag(trap_exit, true), 124 case (catch do_init(Opts)) of 125 {ok, State} -> 126 {ok, State#state{parent = Parent}}; 127 {error, Reason} -> 128 {stop, Reason} 129 end. 130 131do_init(Opts) -> 132 {MgrDir, MgrConf, MgrOpts, AgentTargetName, AgentConf} = parse_opts(Opts), 133 ok = snmp_config:write_manager_config(MgrDir, "", MgrConf), 134 ok = snmpm:start_link(MgrOpts), 135 ok = snmpm:register_user(?USER, ?MODULE, self()), 136 ok = snmpm:register_agent(?USER, AgentTargetName, AgentConf), 137 {ok, #state{agent_target_name = AgentTargetName}}. 138 139 140parse_opts(Opts) -> 141 %% Manager config (written to the manager.conf file) 142 %% Addr = get_opt(addr, Opts, ?HOSTNAME()), 143 Port = get_opt(port, Opts, 5000), 144 EngineId = get_opt(engine_id, Opts, "mgrEngine"), 145 MMS = get_opt(max_message_size, Opts, 484), 146 147 MgrConf = [%% {address, Addr}, 148 {port, Port}, 149 {engine_id, EngineId}, 150 {max_message_size, MMS}], 151 152 153 %% Manager options 154 MgrOpts = get_opt(options, Opts), 155 MgrDir = get_opt(dir, get_opt(config, MgrOpts, [])), 156 157 158 %% Retreive the agent configuration 159 AgentConf = get_opt(agent_config, Opts), 160 AgentTarget = get_opt(agent_target, Opts), 161 {MgrDir, MgrConf, MgrOpts, AgentTarget, AgentConf}. 162 163 164get_opt(Key, Opts) -> 165 case lists:keysearch(Key, 1, Opts) of 166 {value, {Key, Val}} -> 167 Val; 168 false -> 169 throw({error, {missing_mandatory, Key}}) 170 end. 171 172get_opt(Key, Opts, Def) -> 173 case lists:keysearch(Key, 1, Opts) of 174 {value, {Key, Val}} -> 175 Val; 176 false -> 177 Def 178 end. 179 180 181%%-------------------------------------------------------------------- 182%% Func: handle_call/3 183%% Returns: {reply, Reply, State} | 184%% {reply, Reply, State, Timeout} | 185%% {noreply, State} | 186%% {noreply, State, Timeout} | 187%% {stop, Reason, Reply, State} | (terminate/2 is called) 188%% {stop, Reason, State} (terminate/2 is called) 189%%-------------------------------------------------------------------- 190handle_call(stop, _From, S) -> 191 (catch snmpm:stop()), 192 {stop, normal, S}; 193 194handle_call({sync_get, Oids}, _From, 195 #state{agent_target_name = TargetName} = S) -> 196 Reply = (catch snmpm:sync_get2(?USER, TargetName, Oids)), 197 {reply, Reply, S}; 198 199handle_call({sync_get_next, Oids}, _From, 200 #state{agent_target_name = TargetName} = S) -> 201 Reply = (catch snmpm:sync_get_next2(?USER, TargetName, Oids)), 202 {reply, Reply, S}; 203 204handle_call({sync_get_bulk, NR, MR, Oids}, _From, 205 #state{agent_target_name = TargetName} = S) -> 206 Reply = (catch snmpm:sync_get_bulk2(?USER, TargetName, NR, MR, Oids)), 207 {reply, Reply, S}; 208 209handle_call({sync_set, VarsAndVals}, _From, 210 #state{agent_target_name = TargetName} = S) -> 211 Reply = (catch snmpm:sync_set2(?USER, TargetName, VarsAndVals)), 212 {reply, Reply, S}; 213 214handle_call(Req, From, State) -> 215 error_msg("received unknown request ~n~p~nFrom ~p", [Req, From]), 216 {reply, {error, unknown_request}, State}. 217 218 219%%-------------------------------------------------------------------- 220%% Func: handle_cast/2 221%% Returns: {noreply, State} | 222%% {noreply, State, Timeout} | 223%% {stop, Reason, State} (terminate/2 is called) 224%%-------------------------------------------------------------------- 225handle_cast(Msg, State) -> 226 error_msg("received unknown message ~n~p", [Msg]), 227 {noreply, State}. 228 229 230%%-------------------------------------------------------------------- 231%% Func: handle_info/2 232%% Returns: {noreply, State} | 233%% {noreply, State, Timeout} | 234%% {stop, Reason, State} (terminate/2 is called) 235%%-------------------------------------------------------------------- 236handle_info({snmp_error, ReqId, Reason}, 237 #state{parent = P} = State) -> 238 info_msg("received snmp error: " 239 "~n ReqId: ~w" 240 "~n Reason: ~p", [ReqId, Reason]), 241 P ! {snmp_error, ReqId, Reason}, 242 {noreply, State}; 243 244handle_info({snmp_agent, Addr, Port, Info, Pid, _UserData}, 245 #state{parent = P} = State) -> 246 error_msg("detected new agent: " 247 "~n Addr: ~w" 248 "~n Port: ~p" 249 "~n Info: ~p", [Addr, Port, Info]), 250 Pid ! {snmp_agent_reply, ignore, self()}, 251 P ! {snmp_agent, Addr, Port, Info}, 252 {noreply, State}; 253 254handle_info({snmp_pdu, TargetName, ReqId, Resp}, 255 #state{parent = P} = State) -> 256 info_msg("received snmp pdu: " 257 "~n TargetName: ~p" 258 "~n ReqId: ~w" 259 "~n Resp: ~p", [TargetName, ReqId, Resp]), 260 P ! {snmp_pdu, TargetName, ReqId, Resp}, 261 {noreply, State}; 262 263handle_info({snmp_trap, TargetName, Info, Pid}, 264 #state{parent = P} = State) -> 265 info_msg("received snmp trap: " 266 "~n TargetName: ~p" 267 "~n Info: ~p", [TargetName, Info]), 268 Pid ! {snmp_trap_reply, ignore, self()}, 269 P ! {snmp_trap, TargetName, Info}, 270 {noreply, State}; 271 272handle_info({snmp_inform, TargetName, Info, Pid}, 273 #state{parent = P} = State) -> 274 info_msg("received snmp inform: " 275 "~n TargetName: ~p" 276 "~n Info: ~p", [TargetName, Info]), 277 Pid ! {snmp_inform_reply, ignore, self()}, 278 P ! {snmp_inform, TargetName, Info}, 279 {noreply, State}; 280 281handle_info({snmp_report, TargetName, Info, Pid}, 282 #state{parent = P} = State) -> 283 info_msg("received snmp report: " 284 "~n TargetName: ~p" 285 "~n Info: ~p", [TargetName, Info]), 286 Pid ! {snmp_report_reply, ignore, self()}, 287 P ! {snmp_report, TargetName, Info}, 288 {noreply, State}; 289 290handle_info({snmp_invalid_result, In, Out}, State) -> 291 error_msg("Callback failure: " 292 "~n In: ~p" 293 "~n Out: ~p", [In, Out]), 294 {noreply, State}; 295 296handle_info(Info, State) -> 297 error_msg("received unknown info: " 298 "~n Info: ~p", [Info]), 299 {noreply, State}. 300 301 302%%-------------------------------------------------------------------- 303%% Func: terminate/2 304%% Purpose: Shutdown the server 305%% Returns: any (ignored by gen_server) 306%%-------------------------------------------------------------------- 307terminate(_Reason, _State) -> 308 ok. 309 310 311code_change({down, _Vsn}, State, _Extra) -> 312 {ok, State}; 313 314% upgrade 315code_change(_Vsn, State, _Extra) -> 316 {ok, State}. 317 318 319%%%------------------------------------------------------------------- 320%%% Internal functions 321%%%------------------------------------------------------------------- 322 323 324 325 326%% -------------------------------------------------------------------------- 327%% 328%% SNMP manager callback functions 329%% 330%% -------------------------------------------------------------------------- 331 332handle_error(ReqId, Reason, Pid) -> 333 Pid ! {snmp_error, ReqId, Reason}, 334 ignore. 335 336 337handle_agent(Addr, Port, SnmpInfo, Pid, UserData) -> 338 Pid ! {snmp_agent, Addr, Port, SnmpInfo, self(), UserData}, 339 receive 340 {snmp_agent_reply, Reply, Pid} -> 341 Reply 342 after 10000 -> 343 ignore 344 end. 345 346 347handle_pdu(TargetName, ReqId, SnmpResponse, Pid) -> 348 Pid ! {snmp_pdu, TargetName, ReqId, SnmpResponse}, 349 ignore. 350 351 352handle_trap(TargetName, SnmpTrapInfo, Pid) -> 353 Pid ! {snmp_trap, TargetName, SnmpTrapInfo, self()}, 354 receive 355 {snmp_trap_reply, Reply, Pid} -> 356 Reply 357 after 10000 -> 358 ignore 359 end. 360 361 362handle_inform(TargetName, SnmpInfo, Pid) -> 363 Pid ! {snmp_inform, TargetName, SnmpInfo, self()}, 364 receive 365 {snmp_inform_reply, Reply, Pid} -> 366 Reply 367 after 10000 -> 368 ignore 369 end. 370 371 372handle_report(TargetName, SnmpInfo, Pid) -> 373 Pid ! {snmp_report, TargetName, SnmpInfo, self()}, 374 receive 375 {snmp_report_reply, Reply, Pid} -> 376 Reply 377 after 10000 -> 378 ignore 379 end. 380 381 382handle_invalid_result(In, Out, Pid) -> 383 Pid ! {snmp_invalid_result, In, Out}, 384 ignore. 385 386 387%%---------------------------------------------------------------------- 388 389call(Req) -> 390 gen_server:call(?SERVER, Req, infinity). 391 392% cast(Msg) -> 393% gen_server:cast(?SERVER, Msg). 394 395info_msg(F, A) -> 396 catch error_logger:info_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). 397 398error_msg(F, A) -> 399 catch error_logger:error_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). 400 401 402