diff options
Diffstat (limited to 'lib/snmp/examples/ex2/snmp_ex2_manager.erl')
-rw-r--r-- | lib/snmp/examples/ex2/snmp_ex2_manager.erl | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl new file mode 100644 index 0000000000..79cfd94469 --- /dev/null +++ b/lib/snmp/examples/ex2/snmp_ex2_manager.erl @@ -0,0 +1,407 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% This module examplifies how to write test suites for your SNMP agent. +%%---------------------------------------------------------------------- + +-module(snmp_ex2_manager). + +-behaviour(gen_server). +-behaviour(snmpm_user). + +-export([start_link/0, start_link/1, stop/0, + agent/2, + sync_get/2, + sync_get_next/2, + sync_get_bulk/4, + sync_set/2, + + oid_to_name/1 + ]). + +%% Manager callback API: +-export([handle_error/3, + handle_agent/4, + handle_pdu/4, + handle_trap/3, + handle_inform/3, + handle_report/3]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2]). + +-include_lib("snmp/include/snmp_types.hrl"). + + +-define(SERVER, ?MODULE). +-define(USER, ?MODULE). +-define(USER_MOD, ?MODULE). + +-record(state, {parent}). + + +%%%------------------------------------------------------------------- +%%% API +%%%------------------------------------------------------------------- + +start_link() -> + start_link([]). + +start_link(Opts) when is_list(Opts) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [self(), Opts], []). + +stop() -> + cast(stop). + + +%% --- Instruct manager to handle an agent --- + +agent(TargetName, Conf) -> + call({agent, TargetName, Conf}). + + +%% --- Various SNMP operations ---- + +sync_get(TargetName, Oids) -> + call({sync_get, TargetName, Oids}). + +sync_get_next(TargetName, Oids) -> + call({sync_get_next, TargetName, Oids}). + +sync_get_bulk(TargetName, NR, MR, Oids) -> + call({sync_get_bulk, TargetName, NR, MR, Oids}). + +sync_set(TargetName, VarsAndVals) -> + call({sync_set, TargetName, VarsAndVals}). + + +%% --- Misc utility functions --- + +oid_to_name(Oid) -> + call({oid_to_name, Oid}). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +init([Parent, Opts]) -> + process_flag(trap_exit, true), + case (catch do_init(Opts)) of + {ok, State} -> + {ok, State#state{parent = Parent}}; + {error, Reason} -> + {stop, Reason}; + Crap -> + {stop, Crap} + end. + +do_init(Opts) -> + {Dir, MgrConf, MgrOpts} = parse_opts(Opts), + write_config(Dir, MgrConf), + start_manager(MgrOpts), + register_user(), + {ok, #state{}}. + +write_config(Dir, Conf) -> + case snmp_config:write_manager_config(Dir, "", Conf) of + ok -> + ok; + Error -> + error({failed_writing_config, Error}) + end. + +start_manager(Opts) -> + case snmpm:start_link(Opts) of + ok -> + ok; + Error -> + error({failed_starting_manager, Error}) + end. + +register_user() -> + case snmpm:register_user(?USER, ?USER_MOD, self()) of + ok -> + ok; + Error -> + error({failed_register_user, Error}) + end. + +parse_opts(Opts) -> + Port = get_opt(port, Opts, 5000), + EngineId = get_opt(engine_id, Opts, "mgrEngine"), + MMS = get_opt(max_message_size, Opts, 484), + + MgrConf = [{port, Port}, + {engine_id, EngineId}, + {max_message_size, MMS}], + + %% Manager options + Mibs = get_opt(mibs, Opts, []), + Vsns = get_opt(versions, Opts, [v1, v2, v3]), + {ok, Cwd} = file:get_cwd(), + Dir = get_opt(dir, Opts, Cwd), + MgrOpts = [{mibs, Mibs}, + {versions, Vsns}, + %% {server, [{verbosity, trace}]}, + {config, [% {verbosity, trace}, + {dir, Dir}, {db_dir, Dir}]}], + + {Dir, MgrConf, MgrOpts}. + + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- + +handle_call({agent, TargetName, Conf}, _From, S) -> + Reply = (catch snmpm:register_agent(?USER, TargetName, Conf)), + {reply, Reply, S}; + +handle_call({oid_to_name, Oid}, _From, S) -> + Reply = (catch snmpm:oid_to_name(Oid)), + {reply, Reply, S}; + +handle_call({sync_get, TargetName, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_next, TargetName, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get_next(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_bulk, TargetName, NR, MR, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get_bulk(?USER, TargetName, NR, MR, Oids)), + {reply, Reply, S}; + +handle_call({sync_set, TargetName, VarsAndVals}, _From, S) -> + Reply = (catch snmpm:sync_set(?USER, TargetName, VarsAndVals)), + {reply, Reply, S}; + +handle_call(Req, From, State) -> + error_msg("received unknown request ~n~p~nFrom ~p", [Req, From]), + {reply, {error, {unknown_request, Req}}, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast(stop, S) -> + (catch snmpm:stop()), + {stop, normal, S}; + +handle_cast(Msg, State) -> + error_msg("received unknown message ~n~p", [Msg]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info({snmp_callback, Tag, Info}, State) -> + handle_snmp_callback(Tag, Info), + {noreply, State}; + +handle_info(Info, State) -> + error_msg("received unknown info: " + "~n Info: ~p", [Info]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + + +code_change({down, _Vsn}, State, _Extra) -> + {ok, State}; + +% upgrade +code_change(_Vsn, State, _Extra) -> + {ok, State}. + + +%% ======================================================================== +%% ======================================================================== + +handle_snmp_callback(handle_error, {ReqId, Reason}) -> + io:format("*** FAILURE ***" + "~n Request Id: ~p" + "~n Reason: ~p" + "~n", [ReqId, Reason]), + ok; +handle_snmp_callback(handle_agent, {Addr, Port, SnmpInfo}) -> + {ES, EI, VBs} = SnmpInfo, + io:format("*** UNKNOWN AGENT ***" + "~n Address: ~p" + "~n Port: ~p" + "~n SNMP Info: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [Addr, Port, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_pdu, {TargetName, ReqId, SnmpResponse}) -> + {ES, EI, VBs} = SnmpResponse, + io:format("*** Received PDU ***" + "~n TargetName: ~p" + "~n Request Id: ~p" + "~n SNMP response:" + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ReqId, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_trap, {TargetName, SnmpTrap}) -> + TrapStr = + case SnmpTrap of + {Enteprise, Generic, Spec, Timestamp, Varbinds} -> + io_lib:format("~n Generic: ~w" + "~n Exterprise: ~w" + "~n Specific: ~w" + "~n Timestamp: ~w" + "~n Varbinds: ~p", + [Generic, Enteprise, Spec, Timestamp, Varbinds]); + {ErrorStatus, ErrorIndex, Varbinds} -> + io_lib:format("~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [ErrorStatus, ErrorIndex, Varbinds]) + end, + io:format("*** Received TRAP ***" + "~n TargetName: ~p" + "~n SNMP trap: ~s" + "~n", [TargetName, lists:flatten(TrapStr)]), + ok; +handle_snmp_callback(handle_inform, {TargetName, SnmpInform}) -> + {ES, EI, VBs} = SnmpInform, + io:format("*** Received INFORM ***" + "~n TargetName: ~p" + "~n SNMP inform: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_report, {TargetName, SnmpReport}) -> + {ES, EI, VBs} = SnmpReport, + io:format("*** Received REPORT ***" + "~n TargetName: ~p" + "~n SNMP report: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ES, EI, VBs]), + ok; +handle_snmp_callback(BadTag, Crap) -> + io:format("*** Received crap ***" + "~n ~p" + "~n ~p" + "~n", [BadTag, Crap]), + ok. + + + +error(Reason) -> + throw({error, Reason}). + + +error_msg(F, A) -> + catch error_logger:error_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). + + +call(Req) -> + gen_server:call(?SERVER, Req, infinity). + +cast(Msg) -> + gen_server:cast(?SERVER, Msg). + + +%% ======================================================================== +%% Misc internal utility functions +%% ======================================================================== + +%% get_opt(Key, Opts) -> +%% case lists:keysearch(Key, 1, Opts) of +%% {value, {Key, Val}} -> +%% Val; +%% false -> +%% throw({error, {missing_mandatory, Key}}) +%% end. + +get_opt(Key, Opts, Def) -> + case lists:keysearch(Key, 1, Opts) of + {value, {Key, Val}} -> + Val; + false -> + Def + end. + + +%% ======================================================================== +%% SNMPM user callback functions +%% ======================================================================== + +handle_error(ReqId, Reason, Server) when is_pid(Server) -> + report_callback(Server, handle_error, {ReqId, Reason}), + ignore. + + +handle_agent(Addr, Port, SnmpInfo, Server) when is_pid(Server) -> + report_callback(Server, handle_agent, {Addr, Port, SnmpInfo}), + ignore. + + +handle_pdu(TargetName, ReqId, SnmpResponse, Server) when is_pid(Server) -> + report_callback(Server, handle_pdu, {TargetName, ReqId, SnmpResponse}), + ignore. + + +handle_trap(TargetName, SnmpTrap, Server) when is_pid(Server) -> + report_callback(Server, handle_trap, {TargetName, SnmpTrap}), + ok. + +handle_inform(TargetName, SnmpInform, Server) when is_pid(Server) -> + report_callback(Server, handle_inform, {TargetName, SnmpInform}), + ok. + + +handle_report(TargetName, SnmpReport, Server) when is_pid(Server) -> + report_callback(Server, handle_inform, {TargetName, SnmpReport}), + ok. + +report_callback(Pid, Tag, Info) -> + Pid ! {snmp_callback, Tag, Info}. |