diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/common_test/src/ct_snmp.erl | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/common_test/src/ct_snmp.erl')
-rw-r--r-- | lib/common_test/src/ct_snmp.erl | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl new file mode 100644 index 0000000000..7ff88ad7d3 --- /dev/null +++ b/lib/common_test/src/ct_snmp.erl @@ -0,0 +1,771 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-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% +%% + +%%% @doc Common Test user interface module for the OTP snmp application +%%% +%%% The purpose of this module is to make snmp configuration easier for +%%% the test case writer. Many test cases can use default values for common +%%% operations and then no snmp configuration files need to be supplied. When +%%% it is necessary to change particular configuration parameters, a subset +%%% of the relevant snmp configuration files may be passed to <code>ct_snmp</code> +%%% by means of Common Test configuration files. +%%% For more specialized configuration parameters, it is possible to place a +%%% "simple snmp configuration file" in the test suite data directory. +%%% To simplify the test suite, Common Test keeps track +%%% of some of the snmp manager information. This way the test suite doesn't +%%% have to handle as many input parameters as it would if it had to interface the +%%% OTP snmp manager directly. +%%% +%%% <p> The following snmp manager and agent parameters are configurable: </p> +%%% +%%% <pre> +%%% {snmp, +%%% %%% Manager config +%%% [{start_manager, boolean()} % Optional - default is true +%%% {users, [{user_name(), [call_back_module(), user_data()]}]}, %% Optional +%%% {usm_users, [{usm_user_name(), usm_config()}]},%% Optional - snmp v3 only +%%% % managed_agents is optional +%%% {managed_agents,[{agent_name(), [user_name(), agent_ip(), agent_port(), [agent_config()]]}]}, +%%% {max_msg_size, integer()}, % Optional - default is 484 +%%% {mgr_port, integer()}, % Optional - default is 5000 +%%% {engine _id, string()}, % Optional - default is "mgrEngine" +%%% +%%% %%% Agent config +%%% {start_agent, boolean()}, % Optional - default is false +%%% {agent_sysname, string()}, % Optional - default is "ct_test" +%%% {agent_manager_ip, manager_ip()}, % Optional - default is localhost +%%% {agent_vsns, list()}, % Optional - default is [v2] +%%% {agent_trap_udp, integer()}, % Optional - default is 5000 +%%% {agent_udp, integer()}, % Optional - default is 4000 +%%% {agent_notify_type, atom()}, % Optional - default is trap +%%% {agent_sec_type, sec_type()}, % Optional - default is none +%%% {agent_passwd, string()}, % Optional - default is "" +%%% {agent_engine_id, string()}, % Optional - default is "agentEngine" +%%% {agent_max_msg_size, string()},% Optional - default is 484 +%%% +%%% %% The following parameters represents the snmp configuration files +%%% %% context.conf, standard.conf, community.conf, vacm.conf, +%%% %% usm.conf, notify.conf, target_addr.conf and target_params.conf. +%%% %% Note all values in agent.conf can be altered by the parametes +%%% %% above. All these configuration files have default values set +%%% %% up by the snmp application. These values can be overridden by +%%% %% suppling a list of valid configuration values or a file located +%%% %% in the test suites data dir that can produce a list +%%% %% of valid configuration values if you apply file:consult/1 to the +%%% %% file. +%%% {agent_contexts, [term()] | {data_dir_file, rel_path()}}, % Optional +%%% {agent_community, [term()] | {data_dir_file, rel_path()}},% Optional +%%% {agent_sysinfo, [term()] | {data_dir_file, rel_path()}}, % Optional +%%% {agent_vacm, [term()] | {data_dir_file, rel_path()}}, % Optional +%%% {agent_usm, [term()] | {data_dir_file, rel_path()}}, % Optional +%%% {agent_notify_def, [term()] | {data_dir_file, rel_path()}},% Optional +%%% {agent_target_address_def, [term()] | {data_dir_file, rel_path()}},% Optional +%%% {agent_target_param_def, [term()] | {data_dir_file, rel_path()}},% Optional +%%% ]}. +%%% </pre> +%%% +%%% <p>The <code>MgrAgentConfName</code> parameter in the functions +%%% should be a name you allocate in your test suite using a +%%% <code>require</code> statement. +%%% Example (where <code>MgrAgentConfName = snmp_mgr_agent</code>):</p> +%%% <pre> suite() -> [{require, snmp_mgr_agent, snmp}].</pre> +%%% <p>or</p> +%%% <pre> ct:require(snmp_mgr_agent, snmp).</pre> +%%% +%%% <p> Note that Usm users are needed for snmp v3 configuration and are +%%% not to be confused with users.</p> +%%% +%%% <p> Snmp traps, inform and report messages are handled by the +%%% user callback module. For more information about this see +%%% the snmp application. </p> +%%% <p> Note: It is recommended to use the .hrl-files created by the +%%% Erlang/OTP mib-compiler to define the oids. +%%% Example for the getting the erlang node name from the erlNodeTable +%%% in the OTP-MIB:</p> +%%% <pre>Oid = ?erlNodeEntry ++ [?erlNodeName, 1] </pre> +%%% +%%% <p>It is also possible to set values for snmp application configuration +%%% parameters, such as <code>config</code>, <code>server</code>, +%%% <code>net_if</code>, etc (see the "Configuring the application" chapter in +%%% the OTP snmp User's Guide for a list of valid parameters and types). This is +%%% done by defining a configuration data variable on the following form:</p> +%%% <pre> +%%% {snmp_app, [{manager, [snmp_app_manager_params()]}, +%%% {agent, [snmp_app_agent_params()]}]}.</pre> +%%% +%%% <p>A name for the data needs to be allocated in the suite using +%%% <code>require</code> (see example above), and this name passed as +%%% the <code>SnmpAppConfName</code> argument to <code>start/3</code>. +%%% <code>ct_snmp</code> specifies default values for some snmp application +%%% configuration parameters (such as <code>{verbosity,trace}</code> for the +%%% <code>config</code> parameter). This set of defaults will be +%%% merged with the parameters specified by the user, and user values +%%% override <code>ct_snmp</code> defaults.</p> + +-module(ct_snmp). + +%%% Common Types +%%% @type agent_ip() = ip() +%%% @type manager_ip() = ip() +%%% @type agent_name() = atom() +%%% @type ip() = string() | {integer(), integer(), +%%% integer(), integer()} +%%% @type agent_port() = integer() +%%% @type agent_config() = {Item, Value} +%%% @type user_name() = atom() +%%% @type usm_user_name() = string() +%%% @type usm_config() = string() +%%% @type call_back_module() = atom() +%%% @type user_data() = term() +%%% @type oids() = [oid()] +%%% @type oid() = [byte()] +%%% @type snmpreply() = {error_status(), error_index(), varbinds()} +%%% @type error_status() = noError | atom() +%%% @type error_index() = integer() +%%% @type varbinds() = [varbind()] +%%% @type varbind() = term() +%%% @type value_type() = o ('OBJECT IDENTIFIER') | i ('INTEGER') | +%%% u ('Unsigned32') | g ('Unsigned32') | s ('OCTET STRING') +%%% @type varsandvals() = [var_and_val()] +%%% @type var_and_val() = {oid(), value_type(), value()} +%%% @type sec_type() = none | minimum | semi +%%% @type rel_path() = string() +%%% @type snmp_app_manager_params() = term() +%%% @type snmp_app_agent_params() = term() + + +-include("snmp_types.hrl"). +-include("inet.hrl"). +-include("ct.hrl"). + +%%% API +-export([start/2, start/3, stop/1, get_values/3, get_next_values/3, set_values/4, + set_info/1, register_users/2, register_agents/2, register_usm_users/2, + unregister_users/1, unregister_agents/1, update_usm_users/2, + load_mibs/1]). + +%% Manager values +-define(CT_SNMP_LOG_FILE, "ct_snmp_set.log"). +-define(MGR_PORT, 5000). +-define(MAX_MSG_SIZE, 484). +-define(ENGINE_ID, "mgrEngine"). + +%% Agent values +-define(AGENT_ENGINE_ID, "agentEngine"). +-define(TRAP_UDP, 5000). +-define(AGENT_UDP, 4000). +-define(CONF_FILE_VER, [v2]). +-define(AGENT_MAX_MSG_SIZE, 484). +-define(AGENT_NOTIFY_TYPE, trap). +-define(AGENT_SEC_TYPE, none). +-define(AGENT_PASSWD, ""). +%%%========================================================================= +%%% API +%%%========================================================================= + +%%%----------------------------------------------------------------- +%%% @spec start(Config, MgrAgentConfName) -> ok +%%% @equiv start(Config, MgrAgentConfName, undefined) +start(Config, MgrAgentConfName) -> + start(Config, MgrAgentConfName, undefined). + +%%% @spec start(Config, MgrAgentConfName, SnmpAppConfName) -> ok +%%% Config = [{Key, Value}] +%%% Key = atom() +%%% Value = term() +%%% MgrAgentConfName = atom() +%%% SnmpConfName = atom() +%%% +%%% @doc Starts an snmp manager and/or agent. In the manager case, +%%% registrations of users and agents as specified by the configuration +%%% <code>MgrAgentConfName</code> will be performed. When using snmp +%%% v3 also so called usm users will be registered. Note that users, +%%% usm_users and managed agents may also be registered at a later time +%%% using ct_snmp:register_users/2, ct_snmp:register_agents/2, and +%%% ct_snmp:register_usm_users/2. The agent started will be +%%% called <code>snmp_master_agent</code>. Use ct_snmp:load_mibs/1 to load +%%% mibs into the agent. With <code>SnmpAppConfName</code> it's possible +%%% to configure the snmp application with parameters such as <code>config</code>, +%%% <code>mibs</code>, <code>net_if</code>, etc. The values will be merged +%%% with (and possibly override) default values set by <code>ct_snmp</code>. +start(Config, MgrAgentConfName, SnmpAppConfName) -> + StartManager= ct:get_config({MgrAgentConfName, start_manager}, true), + StartAgent = ct:get_config({MgrAgentConfName, start_agent}, false), + + SysName = ct:get_config({MgrAgentConfName, agent_sysname}, "ct_test"), + {ok, HostName} = inet:gethostname(), + {ok, Addr} = inet:getaddr(HostName, inet), + IP = tuple_to_list(Addr), + AgentManagerIP = ct:get_config({MgrAgentConfName, agent_manager_ip}, IP), + + prepare_snmp_env(), + setup_agent(StartAgent, MgrAgentConfName, SnmpAppConfName, + Config, SysName, AgentManagerIP, IP), + setup_manager(StartManager, MgrAgentConfName, SnmpAppConfName, + Config, AgentManagerIP), + application:start(snmp), + + manager_register(StartManager, MgrAgentConfName). + +%%% @spec stop(Config) -> ok +%%% Config = [{Key, Value}] +%%% Key = atom() +%%% Value = term() +%%% +%%% @doc Stops the snmp manager and/or agent removes all files created. +stop(Config) -> + PrivDir = ?config(priv_dir, Config), + application:stop(snmp), + application:stop(mnesia), + MgrDir = filename:join(PrivDir,"mgr"), + ConfDir = filename:join(PrivDir, "conf"), + DbDir = filename:join(PrivDir,"db"), + catch del_dir(MgrDir), + catch del_dir(ConfDir), + catch del_dir(DbDir). + + +%%% @spec get_values(Agent, Oids, MgrAgentConfName) -> SnmpReply +%%% +%%% Agent = agent_name() +%%% Oids = oids() +%%% MgrAgentConfName = atom() +%%% SnmpReply = snmpreply() +%%% +%%% @doc Issues a synchronous snmp get request. +get_values(Agent, Oids, MgrAgentConfName) -> + [Uid, AgentIp, AgentUdpPort | _] = + agent_conf(Agent, MgrAgentConfName), + {ok, SnmpReply, _} = + snmpm:g(Uid, AgentIp, AgentUdpPort, Oids), + SnmpReply. + +%%% @spec get_next_values(Agent, Oids, MgrAgentConfName) -> SnmpReply +%%% +%%% Agent = agent_name() +%%% Oids = oids() +%%% MgrAgentConfName = atom() +%%% SnmpReply = snmpreply() +%%% +%%% @doc Issues a synchronous snmp get next request. +get_next_values(Agent, Oids, MgrAgentConfName) -> + [Uid, AgentIp, AgentUdpPort | _] = + agent_conf(Agent, MgrAgentConfName), + {ok, SnmpReply, _} = + snmpm:gn(Uid, AgentIp, AgentUdpPort, Oids), + SnmpReply. + +%%% @spec set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -> SnmpReply +%%% +%%% Agent = agent_name() +%%% Oids = oids() +%%% MgrAgentConfName = atom() +%%% Config = [{Key, Value}] +%%% SnmpReply = snmpreply() +%%% +%%% @doc Issues a synchronous snmp set request. +set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -> + PrivDir = ?config(priv_dir, Config), + [Uid, AgentIp, AgentUdpPort | _] = + agent_conf(Agent, MgrAgentConfName), + Oids = lists:map(fun({Oid, _, _}) -> Oid end, VarsAndVals), + {ok, SnmpGetReply, _} = + snmpm:g(Uid, AgentIp, AgentUdpPort, Oids), + {ok, SnmpSetReply, _} = + snmpm:s(Uid, AgentIp, AgentUdpPort, VarsAndVals), + case SnmpSetReply of + {noError, 0, _} when PrivDir /= false -> + log(PrivDir, Agent, SnmpGetReply, VarsAndVals); + _ -> + set_failed_or_user_did_not_want_to_log + end, + SnmpSetReply. + +%%% @spec set_info(Config) -> [{Agent, OldVarsAndVals, NewVarsAndVals}] +%%% +%%% Config = [{Key, Value}] +%%% Agent = agent_name() +%%% OldVarsAndVals = varsandvals() +%%% NewVarsAndVals = varsandvals() +%%% +%%% @doc Returns a list of all successful set requests performed in +%%% the test case in reverse order. The list contains the involved +%%% user and agent, the value prior to the set and the new value. This +%%% is intended to facilitate the clean up in the end_per_testcase +%%% function i.e. the undoing of the set requests and its possible +%%% side-effects. +set_info(Config) -> + PrivDir = ?config(priv_dir, Config), + SetLogFile = filename:join(PrivDir, ?CT_SNMP_LOG_FILE), + case file:consult(SetLogFile) of + {ok, SetInfo} -> + file:delete(SetLogFile), + lists:reverse(SetInfo); + _ -> + [] + end. + +%%% @spec register_users(MgrAgentConfName, Users) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% Users = [user()] +%%% Reason = term() +%%% +%%% @doc Register the manager entity (=user) responsible for specific agent(s). +%%% Corresponds to making an entry in users.conf +register_users(MgrAgentConfName, Users) -> + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users, Users}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + setup_users(Users). + +%%% @spec register_agents(MgrAgentConfName, ManagedAgents) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% ManagedAgents = [agent()] +%%% Reason = term() +%%% +%%% @doc Explicitly instruct the manager to handle this agent. +%%% Corresponds to making an entry in agents.conf +register_agents(MgrAgentConfName, ManagedAgents) -> + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, + {managed_agents, ManagedAgents}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + setup_managed_agents(ManagedAgents). + +%%% @spec register_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% UsmUsers = [usm_user()] +%%% Reason = term() +%%% +%%% @doc Explicitly instruct the manager to handle this USM user. +%%% Corresponds to making an entry in usm.conf +register_usm_users(MgrAgentConfName, UsmUsers) -> + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {usm_users, UsmUsers}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), + setup_usm_users(UsmUsers, EngineID). + +%%% @spec unregister_users(MgrAgentConfName) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% Reason = term() +%%% +%%% @doc Removes information added when calling register_users/2. +unregister_users(MgrAgentConfName) -> + Users = lists:map(fun({UserName, _}) -> UserName end, + ct:get_config({MgrAgentConfName, users})), + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users, []}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + takedown_users(Users). + +%%% @spec unregister_agents(MgrAgentConfName) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% Reason = term() +%%% +%%% @doc Removes information added when calling register_agents/2. +unregister_agents(MgrAgentConfName) -> + ManagedAgents = lists:map(fun({_, [Uid, AgentIP, AgentPort, _]}) -> + {Uid, AgentIP, AgentPort} + end, + ct:get_config({MgrAgentConfName, managed_agents})), + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, + {managed_agents, []}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + takedown_managed_agents(ManagedAgents). + + +%%% @spec update_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason} +%%% +%%% MgrAgentConfName = atom() +%%% UsmUsers = usm_users() +%%% Reason = term() +%%% +%%% @doc Alters information added when calling register_usm_users/2. +update_usm_users(MgrAgentConfName, UsmUsers) -> + + {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), + NewSnmpVals = lists:keyreplace(usm_users, 1, SnmpVals, + {usm_users, UsmUsers}), + ct_util:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), + EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), + do_update_usm_users(UsmUsers, EngineID). + +%%% @spec load_mibs(Mibs) -> ok | {error, Reason} +%%% +%%% Mibs = [MibName] +%%% MibName = string() +%%% Reason = term() +%%% +%%% @doc Load the mibs into the agent 'snmp_master_agent'. +load_mibs(Mibs) -> + snmpa:load_mibs(snmp_master_agent, Mibs). + + +%%%======================================================================== +%%% Internal functions +%%%======================================================================== +prepare_snmp_env() -> + %% To make sure application:set_env is not overwritten by any + %% app-file settings. + application:load(snmp), + + %% Fix for older versions of snmp where there are some + %% inappropriate default values for alway starting an + %% agent. + application:unset_env(snmp, agent). +%%%--------------------------------------------------------------------------- +setup_manager(false, _, _, _, _) -> + ok; +setup_manager(true, MgrConfName, SnmpConfName, Config, IP) -> + PrivDir = ?config(priv_dir, Config), + MaxMsgSize = ct:get_config({MgrConfName,max_msg_size}, ?MAX_MSG_SIZE), + Port = ct:get_config({MgrConfName,mgr_port}, ?MGR_PORT), + EngineID = ct:get_config({MgrConfName,engine_id}, ?ENGINE_ID), + MgrDir = filename:join(PrivDir,"mgr"), + %%% Users, Agents and Usms are in test suites register after the + %%% snmp application is started. + Users = [], + Agents = [], + Usms = [], + file:make_dir(MgrDir), + + snmp_config:write_manager_snmp_files(MgrDir, IP, Port, MaxMsgSize, + EngineID, Users, Agents, Usms), + SnmpEnv = merge_snmp_conf([{config, [{dir, MgrDir},{db_dir, MgrDir}, + {verbosity, trace}]}, + {server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {versions, [v1, v2, v3]}], + ct:get_config({SnmpConfName,manager})), + application:set_env(snmp, manager, SnmpEnv). +%%%--------------------------------------------------------------------------- +setup_agent(false,_, _, _, _, _, _) -> + ok; +setup_agent(true, AgentConfName, SnmpConfName, + Config, SysName, ManagerIP, AgentIP) -> + application:start(mnesia), + PrivDir = ?config(priv_dir, Config), + Vsns = ct:get_config({AgentConfName, agent_vsns}, ?CONF_FILE_VER), + TrapUdp = ct:get_config({AgentConfName, agent_trap_udp}, ?TRAP_UDP), + AgentUdp = ct:get_config({AgentConfName, agent_udp}, ?AGENT_UDP), + NotifType = ct:get_config({AgentConfName, agent_notify_type}, + ?AGENT_NOTIFY_TYPE), + SecType = ct:get_config({AgentConfName, agent_sec_type}, ?AGENT_SEC_TYPE), + Passwd = ct:get_config({AgentConfName, agent_passwd}, ?AGENT_PASSWD), + AgentEngineID = ct:get_config({AgentConfName, agent_engine_id}, + ?AGENT_ENGINE_ID), + AgentMaxMsgSize = ct:get_config({AgentConfName, agent_max_msg_size}, + ?MAX_MSG_SIZE), + + ConfDir = filename:join(PrivDir, "conf"), + DbDir = filename:join(PrivDir,"db"), + file:make_dir(ConfDir), + file:make_dir(DbDir), + snmp_config:write_agent_snmp_files(ConfDir, Vsns, ManagerIP, TrapUdp, + AgentIP, AgentUdp, SysName, + atom_to_list(NotifType), + SecType, Passwd, AgentEngineID, + AgentMaxMsgSize), + + override_default_configuration(Config, AgentConfName), + + SnmpEnv = merge_snmp_conf([{db_dir, DbDir}, + {config, [{dir, ConfDir}, + {verbosity, trace}]}, + {agent_type, master}, + {agent_verbosity, trace}, + {net_if, [{verbosity, trace}]}], + ct:get_config({SnmpConfName,agent})), + application:set_env(snmp, agent, SnmpEnv). +%%%--------------------------------------------------------------------------- +merge_snmp_conf(Defaults, undefined) -> + Defaults; +merge_snmp_conf([Def={Key,DefList=[P|_]}|DefParams], UserParams) when is_tuple(P) -> + case lists:keysearch(Key, 1, UserParams) of + false -> + [Def | merge_snmp_conf(DefParams, UserParams)]; + {value,{Key,UserList}} -> + DefList1 = [{SubKey,Val} || {SubKey,Val} <- DefList, + lists:keysearch(SubKey, 1, UserList) == false], + [{Key,DefList1++UserList} | merge_snmp_conf(DefParams, + lists:keydelete(Key, 1, UserParams))] + end; +merge_snmp_conf([Def={Key,_}|DefParams], UserParams) -> + case lists:keysearch(Key, 1, UserParams) of + false -> + [Def | merge_snmp_conf(DefParams, UserParams)]; + {value,_} -> + merge_snmp_conf(DefParams, UserParams) + end; +merge_snmp_conf([], UserParams) -> + UserParams. + + +%%%--------------------------------------------------------------------------- +manager_register(false, _) -> + ok; +manager_register(true, MgrAgentConfName) -> + Agents = ct:get_config({MgrAgentConfName, managed_agents}, []), + Users = ct:get_config({MgrAgentConfName, users}, []), + UsmUsers = ct:get_config({MgrAgentConfName, usm_users}, []), + EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), + + setup_usm_users(UsmUsers, EngineID), + setup_users(Users), + setup_managed_agents(Agents). + +%%%--------------------------------------------------------------------------- +setup_users(Users) -> + lists:foreach(fun({Id, [Module, Data]}) -> + snmpm:register_user(Id, Module, Data) + end, Users). +%%%--------------------------------------------------------------------------- +setup_managed_agents([]) -> + ok; + +setup_managed_agents([{_, [Uid, AgentIp, AgentUdpPort, AgentConf]} | + Rest]) -> + NewAgentIp = case AgentIp of + IpTuple when is_tuple(IpTuple) -> + IpTuple; + HostName when is_list(HostName) -> + {ok,Hostent} = inet:gethostbyname(HostName), + [IpTuple|_] = Hostent#hostent.h_addr_list, + IpTuple + end, + ok = snmpm:register_agent(Uid, NewAgentIp, AgentUdpPort), + lists:foreach(fun({Item, Val}) -> + snmpm:update_agent_info(Uid, NewAgentIp, + AgentUdpPort, Item, Val) + end, AgentConf), + setup_managed_agents(Rest). +%%%--------------------------------------------------------------------------- +setup_usm_users(UsmUsers, EngineID)-> + lists:foreach(fun({UsmUser, Conf}) -> + snmpm:register_usm_user(EngineID, UsmUser, Conf) + end, UsmUsers). +%%%--------------------------------------------------------------------------- +takedown_users(Users) -> + lists:foreach(fun({Id}) -> + snmpm:unregister_user(Id) + end, Users). +%%%--------------------------------------------------------------------------- +takedown_managed_agents([{Uid, AgentIp, AgentUdpPort} | + Rest]) -> + NewAgentIp = case AgentIp of + IpTuple when is_tuple(IpTuple) -> + IpTuple; + HostName when is_list(HostName) -> + {ok,Hostent} = inet:gethostbyname(HostName), + [IpTuple|_] = Hostent#hostent.h_addr_list, + IpTuple + end, + ok = snmpm:unregister_agent(Uid, NewAgentIp, AgentUdpPort), + takedown_managed_agents(Rest); + +takedown_managed_agents([]) -> + ok. +%%%--------------------------------------------------------------------------- +do_update_usm_users(UsmUsers, EngineID) -> + lists:foreach(fun({UsmUser, {Item, Val}}) -> + snmpm:update_usm_user_info(EngineID, UsmUser, + Item, Val) + end, UsmUsers). +%%%--------------------------------------------------------------------------- +log(PrivDir, Agent, {_, _, Varbinds}, NewVarsAndVals) -> + + Fun = fun(#varbind{oid = Oid, variabletype = Type, value = Value}) -> + {Oid, Type, Value} + end, + OldVarsAndVals = lists:map(Fun, Varbinds), + + File = filename:join(PrivDir, ?CT_SNMP_LOG_FILE), + {ok, Fd} = file:open(File, [write, append]), + io:format(Fd, "~p.~n", [{Agent, OldVarsAndVals, NewVarsAndVals}]), + file:close(Fd), + ok. +%%%--------------------------------------------------------------------------- +del_dir(Dir) -> + {ok, Files} = file:list_dir(Dir), + FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end, + Files), + lists:foreach(fun file:delete/1, FullPathFiles), + file:del_dir(Dir), + ok. +%%%--------------------------------------------------------------------------- +agent_conf(Agent, MgrAgentConfName) -> + Agents = ct:get_config({MgrAgentConfName, managed_agents}), + case lists:keysearch(Agent, 1, Agents) of + {value, {Agent, AgentConf}} -> + AgentConf; + _ -> + exit({error, {unknown_agent, Agent, Agents}}) + end. +%%%--------------------------------------------------------------------------- +override_default_configuration(Config, MgrAgentConfName) -> + override_contexts(Config, + ct:get_config({MgrAgentConfName, agent_contexts}, undefined)), + override_community(Config, + ct:get_config({MgrAgentConfName, agent_community}, undefined)), + override_sysinfo(Config, + ct:get_config({MgrAgentConfName, agent_sysinfo}, undefined)), + override_vacm(Config, + ct:get_config({MgrAgentConfName, agent_vacm}, undefined)), + override_usm(Config, + ct:get_config({MgrAgentConfName, agent_usm}, undefined)), + override_notify(Config, + ct:get_config({MgrAgentConfName, agent_notify_def}, undefined)), + override_target_address(Config, + ct:get_config({MgrAgentConfName, + agent_target_address_def}, + undefined)), + override_target_params(Config, + ct:get_config({MgrAgentConfName, agent_target_param_def}, + undefined)). + +%%%--------------------------------------------------------------------------- +override_contexts(_, undefined) -> + ok; + +override_contexts(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, ContextInfo} = file:consult(FullPathFile), + override_contexts(Config, ContextInfo); + +override_contexts(Config, Contexts) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"context.conf"), + file:delete(File), + snmp_config:write_agent_context_config(Dir, "", Contexts). + +%%%--------------------------------------------------------------------------- +override_sysinfo(_, undefined) -> + ok; + +override_sysinfo(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, SysInfo} = file:consult(FullPathFile), + override_sysinfo(Config, SysInfo); + +override_sysinfo(Config, SysInfo) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"standard.conf"), + file:delete(File), + snmp_config:write_agent_standard_config(Dir, "", SysInfo). + +%%%--------------------------------------------------------------------------- +override_target_address(_, undefined) -> + ok; +override_target_address(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, TargetAddressConf} = file:consult(FullPathFile), + override_target_address(Config, TargetAddressConf); + +override_target_address(Config, TargetAddressConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"target_addr.conf"), + file:delete(File), + snmp_config:write_agent_target_addr_config(Dir, "", TargetAddressConf). + + +%%%--------------------------------------------------------------------------- +override_target_params(_, undefined) -> + ok; +override_target_params(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, TargetParamsConf} = file:consult(FullPathFile), + override_target_params(Config, TargetParamsConf); + +override_target_params(Config, TargetParamsConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"target_params.conf"), + file:delete(File), + snmp_config:write_agent_target_params_config(Dir, "", TargetParamsConf). + +%%%--------------------------------------------------------------------------- +override_notify(_, undefined) -> + ok; +override_notify(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, NotifyConf} = file:consult(FullPathFile), + override_notify(Config, NotifyConf); + +override_notify(Config, NotifyConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"notify.conf"), + file:delete(File), + snmp_config:write_agent_notify_config(Dir, "", NotifyConf). + +%%%--------------------------------------------------------------------------- +override_usm(_, undefined) -> + ok; +override_usm(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, UsmConf} = file:consult(FullPathFile), + override_usm(Config, UsmConf); + +override_usm(Config, UsmConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"usm.conf"), + file:delete(File), + snmp_config:write_agent_usm_config(Dir, "", UsmConf). + +%%%-------------------------------------------------------------------------- +override_community(_, undefined) -> + ok; +override_community(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, CommunityConf} = file:consult(FullPathFile), + override_community(Config, CommunityConf); + +override_community(Config, CommunityConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"community.conf"), + file:delete(File), + snmp_config:write_agent_community_config(Dir, "", CommunityConf). + +%%%--------------------------------------------------------------------------- + +override_vacm(_, undefined) -> + ok; +override_vacm(Config, {data_dir_file, File}) -> + Dir = ?config(data_dir, Config), + FullPathFile = filename:join(Dir, File), + {ok, VacmConf} = file:consult(FullPathFile), + override_vacm(Config, VacmConf); + +override_vacm(Config, VacmConf) -> + Dir = ?config(priv_dir, Config), + File = filename:join(Dir,"vacm.conf"), + file:delete(File), + snmp_config:write_agent_vacm_config(Dir, "", VacmConf). |