From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/snmp/test/snmp_agent_test_lib.erl | 1480 +++++++++++++++++++++++++++++++++ 1 file changed, 1480 insertions(+) create mode 100644 lib/snmp/test/snmp_agent_test_lib.erl (limited to 'lib/snmp/test/snmp_agent_test_lib.erl') diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl new file mode 100644 index 0000000000..31b375efa9 --- /dev/null +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -0,0 +1,1480 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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% +%% + +-module(snmp_agent_test_lib). + + +-export([ + start_v1_agent/1, start_v1_agent/2, + start_v2_agent/1, start_v2_agent/2, + start_v3_agent/1, start_v3_agent/2, + start_bilingual_agent/1, start_bilingual_agent/2, + start_mt_agent/1, start_mt_agent/2, + stop_agent/1, + + start_sup/0, stop_sup/2, + start_subagent/3, stop_subagent/1, + start_sub_sup/1, start_sub_sup/2, + + start_node/1, stop_node/1, + + load_master/1, load_master_std/1, unload_master/1, + loaded_mibs/0, unload_mibs/1, + + get_req/2, get_next_req/1, + + config/5, + delete_files/1, + copy_file/2, + update_usm/2, + update_usm_mgr/2, rewrite_usm_mgr/3, reset_usm_mgr/1, + update_community/2, + update_vacm/2, + write_community_conf/2, + write_target_addr_conf/2, write_target_addr_conf/4, + rewrite_target_addr_conf/2, reset_target_addr_conf/1, + write_target_params_conf/2, rewrite_target_params_conf/3, + reset_target_params_conf/1, + write_notify_conf/1, write_view_conf/1, + + display_memory_usage/0, + + init_all/1, finish_all/1, + init_case/1, + try_test/2, try_test/3, try_test/4, + expect/2, expect/3, expect/4, expect/6, + + regs/0, + rpc/3 + ]). + +%% Internal exports +-export([wait/5, run/4]). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). + +-define(TRAP_UDP, 5000). + +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% +%%% finish_mul +%%% +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when is_list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + PrivDir = ?config(priv_dir, Config), + ?DBG("init_all -> PrivDir ~p", [PrivDir]), + + TopDir = filename:join(PrivDir, snmp_agent_test), + case file:make_dir(TopDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + ?FAIL({failed_creating_subsuite_top_dir, Error}) + end, + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + ?line ok = file:make_dir(MgrDir = filename:join(TopDir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + ?line ok = file:make_dir(AgentDir = filename:join(TopDir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + ?line ok = file:make_dir(SaDir = filename:join(TopDir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(TopDir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(TopDir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + + +finish_all(Config) when is_list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + + +%% --- This one *must* be run first in each case --- + +init_case(Config) when is_list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip, tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- + +try_test(Mod, Func) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, [], []]). + +try_test(Mod, Func, A) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, A, []]). + +try_test(Mod, Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> done with exit: " + "~n Rn: ~p" + "~n Loc: ~p", [Rn, Loc]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> done:" + "~n Ret: ~p" + "~n Zed: ~p", [Ret, Zed]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with" + "~n From: ~p" + "~n Env: ~p" + "~n M: ~p" + "~n F: ~p" + "~n A: ~p", [From, Env, M, F, A]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +run(Mod, Func, Args, Opts) -> + ?DBG("run -> entry with" + "~n Mod: ~p" + "~n Func: ~p" + "~n Args: ~p" + "~n Opts: ~p", [Mod, Func, Args, Opts]), + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p", [Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Vsn = get(vsn), + ?DBG("run -> config:" + "~n M: ~p" + "~n Vsn: ~p" + "~n Dir: ~p" + "~n User: ~p" + "~n SecLevel: ~p" + "~n EngineID: ~p" + "~n CtxEngineID: ~p" + "~n Community: ~p" + "~n StdM: ~p", + [M,Vsn,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + Vsn, + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + case (catch apply(Mod, Func, Args)) of + {'EXIT', Reason} -> + catch snmp_test_mgr:stop(), + ?FAIL({apply_failed, {Mod, Func, Args}, Reason}); + Res -> + catch snmp_test_mgr:stop(), + Res + end; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line ?FAIL({mgr_start, Err}) + end. + + +%% --------------------------------------------------------------- +%% --- --- +%% --- Start the agent --- +%% --- --- +%% --------------------------------------------------------------- + +start_v1_agent(Config) when is_list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when is_list(Config) -> + start_agent(Config, [v2]). + +start_v2_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v2], Opts). + +start_v3_agent(Config) when is_list(Config) -> + start_agent(Config, [v3]). + +start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v3], Opts). + +start_bilingual_agent(Config) when is_list(Config) -> + start_agent(Config, [v1,v2]). + +start_bilingual_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v1,v2], Opts). + +start_mt_agent(Config) when is_list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}|Opts]). + +start_agent(Config, Vsns) -> + start_agent(Config, Vsns, []). +start_agent(Config, Vsns, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsns: ~p" + "~n Opts: ~p",[node(), Config, Vsns, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + +%% AgentConfig = +%% [{agent_type, master}, +%% %% {multi_threaded, MultiT}, +%% %% {priority, Prio}, +%% %% {error_report_mod, ErrorReportMod}, +%% {versions, Vsns}, +%% {db_dir, AgentDir}, +%% %% {db_init_error, DbInitError}, +%% %% {set_mechanism, SetModule}, +%% %% {authentication_service, AuthModule}, +%% {audit_trail_log, [{type, read_write}, +%% {dir, AgentDir}, +%% {size, {10240, 10}}, +%% {repair, true}]}, +%% {config, [{verbosity, info}, +%% {dir, AgentDir}, +%% {force_load, false}]}, +%% {mibs, Mibs}, +%% %% {mib_storage, MibStorage}, +%% {local_db, []}, +%% {mib_server, []}, +%% {symbolic_store, []}, +%% {note_store, []}, +%% {net_if, []}, +%% %% {supervisor, SupOpts} +%% ], + + app_env_init(vsn_init(Vsns) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_local_db_verbosity, log}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, log}, + {snmp_symbolic_store_verbosity, log}, + {snmp_note_store_verbosity, log}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + ?line Sup = start_sup(), + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = start_sub_sup(SaNode, SaDir), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +app_env_init(Env0, Opts) -> + ?DBG("app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key, Val} = New, Acc0) -> + ?DBG("app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + +stop_agent(Config) when is_list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + + Info = agent_info(Sup), + ?DBG("stop_agent -> Agent info: " + "~n ~p", [Info]), + + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +start_sup() -> + case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + ?FAIL({start_failed,Else, ?IS_MNESIA_RUNNING()}) + end. + +stop_sup(Pid, _) when (node(Pid) =:= node()) -> + case (catch process_info(Pid)) of + PI when is_list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +%% --- start subagent supervisor --- + +start_sub_sup(Node, Dir) -> + rpc:call(Node, ?MODULE, start_sub_sup, [Dir]). + +start_sub_sup(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + + +%% --- start and stop subagents --- + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + Mod = snmpa_supervisor, + Func = start_sub_agent, + Args = [MA, RegTree, [Mib1]], + case rpc:call(SaNode, Mod, Func, Args) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + + +%% --- various mib load/unload functions --- + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + + +agent_info(Sup) -> + ?DBG("agent_info -> entry with" + "~n Sup: ~p", [Sup]), + rpc:call(node(Sup), snmpa, info, []). + + +%% --- + +expect(Id, A) -> + Fun = fun() -> do_expect(A) end, + expect2(Id, Fun). + +expect(Id, A, B) -> + Fun = fun() -> do_expect(A, B) end, + expect2(Id, Fun). + +expect(Id, A, B, C) -> + Fun = fun() -> do_expect(A, B, C) end, + expect2(Id, Fun). + +expect(Id, A, B, C, D, E) -> + Fun = fun() -> do_expect(A, B, C, D, E) end, + expect2(Id, Fun). + +expect2(Id, F) -> + io:format("~w:expect2 -> entry with" + "~n Id: ~w" + "~n", [?MODULE, Id]), + case F() of + {error, Reason} -> + {error, Id, Reason}; + Else -> + io:format("~w:expect2 -> " + "~n Id: ~w" + "~n Else: ~p" + "~n", [?MODULE, Id, Else]), + Else + end. + + +%% ---------------------------------------------------------------------- + +get_timeout() -> + get_timeout(os:type()). + +get_timeout(vxworks) -> 7000; +get_timeout(_) -> 3500. + +receive_pdu(To) -> + receive + {snmp_pdu, PDU} when is_record(PDU, pdu) -> + PDU + after To -> + {error, timeout} + end. + +receive_trap(To) -> + receive + {snmp_pdu, PDU} when is_record(PDU, trappdu) -> + PDU + after To -> + {error, timeout} + end. + + +do_expect(Expect) when is_atom(Expect) -> + do_expect({Expect, get_timeout()}); + +do_expect({any_pdu, To}) + when is_integer(To) orelse (To =:= infinity) -> + io:format("~w:do_expect(any_pdu) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive_pdu(To); + +do_expect({any_trap, To}) -> + io:format("~w:do_expect(any_trap) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive_trap(To); + +do_expect({timeout, To}) -> + io:format("~w:do_expect(timeout) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive + X -> + {error, {unexpected, X}} + after + To -> + ok + end; + +do_expect({Err, To}) + when is_atom(Err) andalso (is_integer(To) orelse (To =:= infinity)) -> + do_expect({{error, Err}, To}); + +do_expect({error, Err}) when is_atom(Err) -> + Check = fun(_, R) -> R end, + do_expect2(Check, any, Err, any, any, get_timeout()); +do_expect({{error, Err}, To}) -> + Check = fun(_, R) -> R end, + do_expect2(Check, any, Err, any, any, To); + +%% exp_varbinds() -> [exp_varbind()] +%% exp_varbind() -> any | {Oid, any} | {Oid, Value} +%% Oid -> [integer()] +%% Value -> term() +%% ExpVBs -> exp_varbinds() | {VbsCondition, exp_varbinds()} +do_expect(ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'get-response', noError, 0, ExpVBs, get_timeout()). + + +do_expect(v2trap, ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'snmpv2-trap', noError, 0, ExpVBs, get_timeout()); + + +do_expect(report, ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'report', noError, 0, ExpVBs, get_timeout()); + + +do_expect(inform, ExpVBs) -> + do_expect({inform, true}, ExpVBs); + +do_expect({inform, false}, ExpVBs) -> + io:format("~w:do_expect(inform, false) -> entry with" + "~n ExpVBs: ~p" + "~n", [?MODULE, ExpVBs]), + Check = fun(_, R) -> R end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); + +do_expect({inform, true}, ExpVBs) -> + io:format("~w:do_expect(inform, true) -> entry with" + "~n ExpVBs: ~p" + "~n", [?MODULE, ExpVBs]), + Check = + fun(PDU, ok) -> + RespPDU = PDU#pdu{type = 'get-response', + error_status = noError, + error_index = 0}, + snmp_test_mgr:rpl(RespPDU), + ok; + (_, Err) -> + Err + end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); + +do_expect({inform, {error, EStat, EIdx}}, ExpVBs) + when is_atom(EStat) andalso is_integer(EIdx) -> + Check = + fun(PDU, ok) -> + RespPDU = PDU#pdu{type = 'get-response', + error_status = EStat, + error_index = EIdx}, + snmp_test_mgr:rpl(RespPDU), + ok; + (_, Err) -> + Err + end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()). + + +do_expect(Err, Idx, ExpVBs) -> + do_expect(Err, Idx, ExpVBs, get_timeout()). + +do_expect(Err, Idx, ExpVBs, To) + when is_atom(Err) andalso + (is_integer(Idx) orelse is_list(Idx) orelse (Idx == any)) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'get-response', Err, Idx, ExpVBs, To). + + +do_expect(Type, Enterp, Generic, Specific, ExpVBs) -> + do_expect(Type, Enterp, Generic, Specific, ExpVBs, 3500). + +do_expect(trap, Enterp, Generic, Specific, ExpVBs, To) -> + io:format("~w:do_expect(trap) -> entry with" + "~n Enterp: ~w" + "~n Generic: ~w" + "~n Specific: ~w" + "~n ExpVBs: ~w" + "~n To: ~w" + "~nwhen" + "~n Time: ~w" + "~n", [?MODULE, Enterp, Generic, Specific, ExpVBs, To, t()]), + PureE = purify_oid(Enterp), + case receive_trap(To) of + #trappdu{enterprise = PureE, + generic_trap = Generic, + specific_trap = Specific, + varbinds = VBs} -> + check_vbs(purify_oids(ExpVBs), VBs); + + #trappdu{enterprise = Ent2, + generic_trap = G2, + specific_trap = Spec2, + varbinds = VBs} -> + {error, {unexpected_trap, + {PureE, Generic, Specific, ExpVBs}, + {Ent2, G2, Spec2, VBs}}}; + + Error -> + Error + end. + + +do_expect2(Check, Type, Err, Idx, ExpVBs, To) + when is_function(Check) andalso + is_atom(Type) andalso + is_atom(Err) andalso + (is_integer(Idx) orelse is_list(Idx) orelse (Idx =:= any)) andalso + (is_list(ExpVBs) orelse (ExpVBs =:= any)) andalso + (is_integer(To) orelse (To =:= infinity)) -> + + io:format("~w:do_expect2 -> entry with" + "~n Type: ~w" + "~n Err: ~w" + "~n Idx: ~w" + "~n ExpVBs: ~w" + "~n To: ~w" + "~nwhen" + "~n Time: ~w" + "~n", [?MODULE, Type, Err, Idx, ExpVBs, To, t()]), + + case receive_pdu(To) of + + #pdu{type = Type, + error_status = Err, + error_index = Idx} when ExpVBs =:= any -> + ok; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2, + error_index = Idx} when ExpVBs =:= any -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{error_status = Err} when (Type =:= any) andalso + (Idx =:= any) andalso + (ExpVBs =:= any) -> + ok; + + #pdu{request_id = ReqId, + error_status = Err2} when (Type =:= any) andalso + (Idx =:= any) andalso + (ExpVBs =:= any) -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{type = Type, + error_status = Err} when (Idx =:= any) andalso + (ExpVBs =:= any) -> + ok; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2} when (Idx =:= any) andalso + (ExpVBs =:= any) -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err, + error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> + case lists:member(EI, Idx) of + true -> + ok; + false -> + {error, {unexpected_error_index, EI, Idx, ReqId}} + end; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2, + error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> + case lists:member(EI, Idx) of + true -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + false -> + {error, {unexpected_error, {Err, Idx}, {Err2, EI}, ReqId}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Idx2} when ExpVBs =:= any -> + {error, + {unexpected_pdu, + {Type, Err, Idx}, {Type2, Err2, Idx2}, ReqId}}; + + #pdu{type = Type, + error_status = Err, + error_index = Idx, + varbinds = VBs} = PDU -> + Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); + + #pdu{type = Type, + error_status = Err, + varbinds = VBs} = PDU when Idx =:= any -> + Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); + + #pdu{type = Type, + request_id = ReqId, + error_status = Err, + error_index = EI, + varbinds = VBs} = PDU when is_list(Idx) -> + PureVBs = purify_oids(ExpVBs), + case lists:member(EI, Idx) of + true -> + Check(PDU, check_vbs(PureVBs, VBs)); + false -> + {error, {unexpected_error_index, Idx, EI, ReqId}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Idx2, + varbinds = VBs2} -> + {error, + {unexpected_pdu, + {Type, Err, Idx, purify_oids(ExpVBs)}, + {Type2, Err2, Idx2, VBs2}, + ReqId}}; + + Error -> + Error + end. + + + +check_vbs([], []) -> + ok; +check_vbs(Exp, []) -> + {error, {to_few_vbs, Exp}}; +check_vbs([], VBs) -> + {error, {to_many_vbs, VBs}}; +check_vbs([any|Exp], [_|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, any}|Exp], [#varbind{oid = Oid}|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, Val}|Exp], [#varbind{oid = Oid, value = Val}|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, Val1}|_], [#varbind{oid = Oid, value = Val2}|_]) -> + {error, {unexpected_vb_value, Oid, Val1, Val2}}; +check_vbs([{Oid1, _}|_], [#varbind{oid = Oid2}|_]) -> + {error, {unexpected_vb_oid, Oid1, Oid2}}. + + +purify_oids({VbsCondition, VBs}) + when ((VbsCondition =:= true) orelse (VbsCondition =:= false)) andalso + is_list(VBs) -> + {VbsCondition, do_purify_oids(VBs)}; +purify_oids(VBs) when is_list(VBs) -> + do_purify_oids(VBs). + +do_purify_oids([]) -> + []; +do_purify_oids([{XOid, Q}|T]) -> + [{purify_oid(XOid), Q} | do_purify_oids(T)]. + + +purify_oid(Oid) -> + io:format("~w:purify_oid -> entry with" + "~n Oid: ~w" + "~n", + [?MODULE, Oid]), + case (catch snmp_test_mgr:purify_oid(Oid)) of + {error, Reason} -> + io:format("~w:purify_oid -> error: " + "~n Reason: ~p" + "~n", + [?MODULE, Reason]), + exit({malformed_oid, Reason}); + {ok, Oid2} when is_list(Oid2) -> + io:format("~w:purify_oid -> ok: " + "~n Oid2: ~p" + "~n", + [?MODULE, Oid2]), + Oid2; + Error -> + io:format("~w:purify_oid -> unexpected return value: " + "~n Error: ~p" + "~n", + [?MODULE, Error]), + exit({unexpected_purify_result, Error}) + + end. + + +%% ---------------------------------------------------------------------- + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with" + "~n Id: ~p" + "~n Vars: ~p",[Id,Vars]), + snmp_test_mgr:g(Vars), + ?DBG("get_req -> await response",[]), + case snmp_test_mgr:get_response(Id, Vars) of + {ok, Val} -> + ?DBG("get_req -> response: ~p",[Val]), + Val; + {error, _, {ExpFmt, ExpArg}, {ActFmt, ActArg}} -> + ?DBG("get_req -> error for ~p: " + "~n " ++ ExpFmt ++ + "~n " ++ ActFmt, + [Id] ++ ExpArg ++ ActArg), + exit({unexpected_response, ExpArg, ActArg}); + Error -> + ?DBG("get_req -> error: ~n~p",[Error]), + exit({unknown, Error}) + end. + + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with" + "~n Vars: ~p",[Vars]), + snmp_test_mgr:gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + +%% --- start and stop nodes --- + +start_node(Name) -> + ?LOG("start_node -> entry with" + "~n Name: ~p" + "~n when" + "~n hostname of this node: ~p", + [Name, list_to_atom(?HOSTNAME(node()))]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- + +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + Conf = [{"agentEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"agentEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"agentEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, + + {"mgrEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"mgrEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"mgrEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], + ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, + + {"mgrEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], + + ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", ShaKey, DesKey}, + {"mgrEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", ShaKey, DesKey}], + ok = snmp_config:write_agent_usm_config(Dir, "", Conf). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> + ok; +update_community(_, Dir) -> + Conf = [{"no-rights", "no-rights", "no-rights", "", ""}], + ?line ok = snmp_config:update_agent_community_config(Dir, Conf). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + Conf = [{vacmSecurityToGroup, usm, "authMD5", "initial"}, + {vacmSecurityToGroup, usm, "authSHA", "initial"}, + {vacmSecurityToGroup, usm, "privDES", "initial"}, + {vacmSecurityToGroup, usm, "newUser", "initial"}, + {vacmViewTreeFamily, "internet", ?tDescr_instance, + excluded, null}], + ?line ok = snmp_config:update_agent_vacm_config(Dir, Conf). + + +write_community_conf(Dir, Conf) -> + snmp_config:write_agent_community_config(Dir, "", Conf). + +write_target_addr_conf(Dir, Conf) -> + snmp_config:write_agent_target_addr_config(Dir, "", Conf). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + snmp_config:write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, Vsns). + +rewrite_target_addr_conf(Dir, NewPort) -> + ?DBG("rewrite_target_addr_conf -> entry with" + "~n NewPort: ~p", [NewPort]), + TAFile = filename:join(Dir, "target_addr.conf"), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile, + fun(R) -> rewrite_target_addr_conf_check(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + + ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs). + +rewrite_target_addr_conf_check(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; + (v2) -> {"target_v2", v2c, v2c, "all-rights", noAuthNoPriv}; + (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} + end, + Conf = [F(Vsn) || Vsn <- Vsns], + snmp_config:write_agent_target_params_config(Dir, "", Conf). + +rewrite_target_params_conf(Dir, SecName, SecLevel) + when is_list(SecName) andalso is_atom(SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + Conf = [{"target_v3", v3, usm, SecName, SecLevel}], + snmp_config:write_agent_target_params_config(Dir, "", Conf). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + Conf = [{"standard trap", "std_trap", trap}, + {"standard inform", "std_inform", inform}], + snmp_config:write_agent_notify_config(Dir, "", Conf). + +write_view_conf(Dir) -> + Conf = [{2, [1,3,6], included, null}, + {2, ?tDescr_instance, excluded, null}], + snmp_config:write_agent_view_config(Dir, "", Conf). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = key1search(tree_size_bytes, Info), + ProcMem = key1search(process_memory, Info), + MibDbSize = key1search([db_memory,mib], Info), + NodeDbSize = key1search([db_memory,node], Info), + TreeDbSize = key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +key1search([], Res) -> + Res; +key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + key1search(Keys, Val); + false -> + undefined + end; +key1search(Key, List) when is_atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). + + +rpc(Node, F, A) -> + rpc:call(Node, snmpa, F, A). + + +%% await_pdu(To) -> +%% await_response(To, pdu). +%% +%% await_trap(To) -> +%% await_response(To, trap). +%% +%% await_any(To) -> +%% await_response(To, any). +%% +%% +%% await_response(To, What) -> +%% await_response(To, What, []). +%% +%% await_response(To, What, Stuff) when is_integer(To) andalso (To >= 0) -> +%% T = t(), +%% receive +%% {snmp_pdu, PDU} when is_record(Trap, pdu) andalso (What =:= pdu) -> +%% {ok, PDU}; +%% {snmp_pdu, Trap} is_when record(Trap, trappdu) andalso (What =:= trap) -> +%% {ok, Trap}; +%% Any when What =:= any -> +%% {ok, Any}; +%% Any -> +%% %% Recalc time +%% NewTo = To - (t() - T) +%% await_reponse(NewTo, What, [{NewTo, Any}|Stuff]) +%% after To -> +%% {error, {timeout, Stuff}} +%% end; +%% await_response(_, Stuff) -> +%% {error, {timeout, Stuff}}. +%% +%% +%% t() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). +%% +%% +%% timeout() -> +%% timeout(os:type()). +%% +%% timeout(vxworks) -> 7000; +%% timeout(_) -> 3500. + + +%% Time in milli seconds +t() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). -- cgit v1.2.3