diff options
Diffstat (limited to 'lib/common_test/src')
-rw-r--r-- | lib/common_test/src/ct.erl | 5 | ||||
-rw-r--r-- | lib/common_test/src/ct_framework.erl | 6 | ||||
-rw-r--r-- | lib/common_test/src/ct_master.erl | 7 | ||||
-rw-r--r-- | lib/common_test/src/ct_master_logs.erl | 41 | ||||
-rw-r--r-- | lib/common_test/src/ct_run.erl | 53 | ||||
-rw-r--r-- | lib/common_test/src/ct_slave.erl | 51 | ||||
-rw-r--r-- | lib/common_test/src/ct_snmp.erl | 335 | ||||
-rw-r--r-- | lib/common_test/src/ct_testspec.erl | 4 | ||||
-rw-r--r-- | lib/common_test/src/ct_util.hrl | 1 | ||||
-rw-r--r-- | lib/common_test/src/cth_log_redirect.erl | 2 |
10 files changed, 334 insertions, 171 deletions
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index ad9bf4e2d6..8eafdff29f 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -148,7 +148,7 @@ run(TestDirs) -> %%% {config,CfgFiles} | {userconfig, UserConfig} | %%% {allow_user_terms,Bool} | {logdir,LogDir} | %%% {silent_connections,Conns} | {stylesheet,CSSFile} | -%%% {cover,CoverSpecFile} | {step,StepOpts} | +%%% {cover,CoverSpecFile} | {cover_stop,Bool} | {step,StepOpts} | %%% {event_handler,EventHandlers} | {include,InclDirs} | %%% {auto_compile,Bool} | {create_priv_dir,CreatePrivDir} | %%% {multiply_timetraps,M} | {scale_timetraps,Bool} | @@ -988,8 +988,9 @@ get_testdata(Key) -> end. %%%----------------------------------------------------------------- -%%% @spec abort_current_testcase(Reason) -> ok | {error,no_testcase_running} +%%% @spec abort_current_testcase(Reason) -> ok | {error,ErrorReason} %%% Reason = term() +%%% ErrorReason = no_testcase_running | parallel_group %%% %%% @doc <p>When calling this function, the currently executing test case will be aborted. %%% It is the user's responsibility to know for sure which test case is currently diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 403eab66cb..c1abf27e9f 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1191,6 +1191,12 @@ report(What,Data) -> end; tests_done -> ok; + severe_error -> + ct_event:sync_notify(#event{name=What, + node=node(), + data=Data}), + ct_util:set_testdata({What,Data}), + ok; tc_start -> %% Data = {{Suite,Func},LogFileName} ct_event:sync_notify(#event{name=tc_logfile, diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl index 042c5ba267..f29eba605c 100644 --- a/lib/common_test/src/ct_master.erl +++ b/lib/common_test/src/ct_master.erl @@ -51,7 +51,7 @@ %%% {testcase,Cases} | {spec,TestSpecs} | {allow_user_terms,Bool} | %%% {logdir,LogDir} | {event_handler,EventHandlers} | %%% {silent_connections,Conns} | {cover,CoverSpecFile} | -%%% {userconfig, UserCfgFiles} +%%% {cover_stop,Bool} | {userconfig, UserCfgFiles} %%% CfgFiles = string() | [string()] %%% TestDirs = string() | [string()] %%% Suites = atom() | [atom()] @@ -696,8 +696,9 @@ status(MasterPid,Event) -> log(To,Heading,Str,Args) -> if To == all ; To == tty -> - Str1 = ["=== ",Heading," ===\n",io_lib:format(Str,Args),"\n"], - io:format(Str1,[]); + Chars = ["=== ",Heading," ===\n", + io_lib:format(Str,Args),"\n"], + io:put_chars(Chars); true -> ok end, diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl index 9e61d5b16f..84f175c0a9 100644 --- a/lib/common_test/src/ct_master_logs.erl +++ b/lib/common_test/src/ct_master_logs.erl @@ -134,7 +134,7 @@ init(Parent,LogDir,Nodes) -> io:format(CtLogFd,int_header(),[log_timestamp(now()),"Test Nodes\n"]), io:format(CtLogFd,"~s\n",[NodeStr]), - io:format(CtLogFd,int_footer()++"\n",[]), + io:put_chars(CtLogFd,[int_footer(),"\n"]), NodeDirIxFd = open_nodedir_index(RunDirAbs,Time), Parent ! {started,self(),{Time,RunDirAbs}}, @@ -202,24 +202,21 @@ loop(State) -> open_ct_master_log(Dir) -> FullName = filename:join(Dir,?ct_master_log_name), {ok,Fd} = file:open(FullName,[write]), - io:format(Fd,header("Common Test Master Log", {[],[1,2],[]}),[]), + io:put_chars(Fd,header("Common Test Master Log", {[],[1,2],[]})), %% maybe add config info here later - io:format(Fd, config_table([]), []), - io:format(Fd, - "<style>\n" - "div.ct_internal { background:lightgrey; color:black }\n" - "div.default { background:lightgreen; color:black }\n" - "</style>\n", - []), - io:format(Fd, - xhtml("<br><h2>Progress Log</h2>\n<pre>\n", - "<br /><h2>Progress Log</h2>\n<pre>\n"), - []), + io:put_chars(Fd,config_table([])), + io:put_chars(Fd, + "<style>\n" + "div.ct_internal { background:lightgrey; color:black }\n" + "div.default { background:lightgreen; color:black }\n" + "</style>\n"), + io:put_chars(Fd, + xhtml("<br><h2>Progress Log</h2>\n<pre>\n", + "<br /><h2>Progress Log</h2>\n<pre>\n")), Fd. close_ct_master_log(Fd) -> - io:format(Fd,"</pre>",[]), - io:format(Fd,footer(),[]), + io:put_chars(Fd,["</pre>",footer()]), file:close(Fd). config_table(Vars) -> @@ -248,20 +245,20 @@ int_footer() -> open_nodedir_index(Dir,StartTime) -> FullName = filename:join(Dir,?nodedir_index_name), {ok,Fd} = file:open(FullName,[write]), - io:format(Fd,nodedir_index_header(StartTime),[]), + io:put_chars(Fd,nodedir_index_header(StartTime)), Fd. print_nodedir(Node,RunDir,Fd) -> Index = filename:join(RunDir,"index.html"), - io:format(Fd, - ["<tr>\n" - "<td align=center>",atom_to_list(Node),"</td>\n", - "<td align=left><a href=\"",Index,"\">",Index,"</a></td>\n", - "</tr>\n"],[]), + io:put_chars(Fd, + ["<tr>\n" + "<td align=center>",atom_to_list(Node),"</td>\n", + "<td align=left><a href=\"",Index,"\">",Index,"</a></td>\n", + "</tr>\n"]), ok. close_nodedir_index(Fd) -> - io:format(Fd,index_footer(),[]), + io:put_chars(Fd,index_footer()), file:close(Fd). nodedir_index_header(StartTime) -> diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 96b2934382..eb05c90ba8 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -58,6 +58,7 @@ vts, shell, cover, + cover_stop, coverspec, step, logdir, @@ -245,6 +246,7 @@ script_start1(Parent, Args) -> Vts = get_start_opt(vts, true, Args), Shell = get_start_opt(shell, true, Args), Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args), + CoverStop = get_start_opt(cover_stop, fun([CS]) -> list_to_atom(CS) end, Args), LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args), LogOpts = get_start_opt(logopts, fun(Os) -> [list_to_atom(O) || O <- Os] end, [], Args), @@ -329,7 +331,8 @@ script_start1(Parent, Args) -> end, StartOpts = #opts{label = Label, profile = Profile, - vts = Vts, shell = Shell, cover = Cover, + vts = Vts, shell = Shell, + cover = Cover, cover_stop = CoverStop, logdir = LogDir, logopts = LogOpts, basic_html = BasicHtml, verbosity = Verbosity, @@ -416,6 +419,9 @@ script_start2(StartOpts = #opts{vts = undefined, Cover = choose_val(StartOpts#opts.cover, SpecStartOpts#opts.cover), + CoverStop = + choose_val(StartOpts#opts.cover_stop, + SpecStartOpts#opts.cover_stop), MultTT = choose_val(StartOpts#opts.multiply_timetraps, SpecStartOpts#opts.multiply_timetraps), @@ -475,6 +481,7 @@ script_start2(StartOpts = #opts{vts = undefined, profile = Profile, testspecs = Specs, cover = Cover, + cover_stop = CoverStop, logdir = LogDir, logopts = AllLogOpts, basic_html = BasicHtml, @@ -723,6 +730,7 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" + "\n\t[-cover_stop Bool]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" @@ -745,6 +753,7 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" + "\n\t[-cover_stop Bool]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" @@ -938,6 +947,7 @@ run_test2(StartOpts) -> %% code coverage Cover = get_start_opt(cover, fun(CoverFile) -> ?abs(CoverFile) end, StartOpts), + CoverStop = get_start_opt(cover_stop, value, StartOpts), %% timetrap manipulation MultiplyTT = get_start_opt(multiply_timetraps, value, 1, StartOpts), @@ -1000,7 +1010,8 @@ run_test2(StartOpts) -> Step = get_start_opt(step, value, StartOpts), Opts = #opts{label = Label, profile = Profile, - cover = Cover, step = Step, logdir = LogDir, + cover = Cover, cover_stop = CoverStop, + step = Step, logdir = LogDir, logopts = LogOpts, basic_html = BasicHtml, config = CfgFiles, verbosity = Verbosity, @@ -1063,6 +1074,8 @@ run_spec_file(Relaxed, AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]), Cover = choose_val(Opts#opts.cover, SpecOpts#opts.cover), + CoverStop = choose_val(Opts#opts.cover_stop, + SpecOpts#opts.cover_stop), MultTT = choose_val(Opts#opts.multiply_timetraps, SpecOpts#opts.multiply_timetraps), ScaleTT = choose_val(Opts#opts.scale_timetraps, @@ -1103,6 +1116,7 @@ run_spec_file(Relaxed, Opts1 = Opts#opts{label = Label, profile = Profile, cover = Cover, + cover_stop = CoverStop, logdir = which(logdir, LogDir), logopts = AllLogOpts, stylesheet = Stylesheet, @@ -1376,6 +1390,7 @@ get_data_for_node(#testspec{label = Labels, verbosity = VLvls, silent_connections = SilentConnsList, cover = CoverFs, + cover_stop = CoverStops, config = Cfgs, userconfig = UsrCfgs, event_handler = EvHs, @@ -1407,6 +1422,7 @@ get_data_for_node(#testspec{label = Labels, SCs -> SCs end, Cover = proplists:get_value(Node, CoverFs), + CoverStop = proplists:get_value(Node, CoverStops), MT = proplists:get_value(Node, MTs), ST = proplists:get_value(Node, STs), CreatePrivDir = proplists:get_value(Node, PDs), @@ -1425,6 +1441,7 @@ get_data_for_node(#testspec{label = Labels, verbosity = Verbosity, silent_connections = SilentConns, cover = Cover, + cover_stop = CoverStop, config = ConfigFiles, event_handlers = EvHandlers, ct_hooks = FiltCTHooks, @@ -1597,14 +1614,7 @@ do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc), StepOpts -> #opts{step = StepOpts} end, - Opts1 = - case proplists:get_value(cover, Misc) of - undefined -> - Opts; - CoverFile -> - Opts#opts{cover = CoverFile} - end, - do_run(Tests, [], Opts1#opts{logdir = LogDir}, []); + do_run(Tests, [], Opts#opts{logdir = LogDir}, []); do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> #opts{label = Label, profile = Profile, cover = Cover, @@ -1638,7 +1648,13 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> {error,Reason} -> exit({error,Reason}); CoverSpec -> - Opts#opts{coverspec = CoverSpec} + CoverStop = + case Opts#opts.cover_stop of + undefined -> true; + Stop -> Stop + end, + Opts#opts{coverspec = CoverSpec, + cover_stop = CoverStop} end end, %% This env variable is used by test_server to determine @@ -2144,7 +2160,8 @@ do_run_test(Tests, Skip, Opts) -> %% tell test_server which modules should be cover compiled %% note that actual compilation is done when tests start test_server_ctrl:cover(CovApp, CovFile, CovExcl, CovIncl, - CovCross, CovExport, CovLevel), + CovCross, CovExport, CovLevel, + Opts#opts.cover_stop), %% save cover data (used e.g. to add nodes dynamically) ct_util:set_testdata({cover,CovData}), %% start cover on specified nodes @@ -2216,6 +2233,15 @@ do_run_test(Tests, Skip, Opts) -> end, CleanUp), [code:del_path(Dir) || Dir <- AddedToPath], + %% If a severe error has occurred in the test_server, + %% we will generate an exception here. + case ct_util:get_testdata(severe_error) of + undefined -> ok; + SevereError -> + ct_logs:log("SEVERE ERROR", "~p\n", [SevereError]), + exit(SevereError) + end, + case ct_util:get_testdata(stats) of Stats = {_Ok,_Failed,{_UserSkipped,_AutoSkipped}} -> Stats; @@ -2618,6 +2644,9 @@ merge_arguments([LogDir={logdir,_}|Args], Merged) -> merge_arguments([CoverFile={cover,_}|Args], Merged) -> merge_arguments(Args, handle_arg(replace, CoverFile, Merged)); +merge_arguments([CoverStop={cover_stop,_}|Args], Merged) -> + merge_arguments(Args, handle_arg(replace, CoverStop, Merged)); + merge_arguments([{'case',TC}|Args], Merged) -> merge_arguments(Args, handle_arg(merge, {testcase,TC}, Merged)); diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl index aa3413fa89..58633b7de6 100644 --- a/lib/common_test/src/ct_slave.erl +++ b/lib/common_test/src/ct_slave.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2012. 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 @@ -37,7 +37,7 @@ -record(options, {username, password, boot_timeout, init_timeout, startup_timeout, startup_functions, monitor_master, - kill_if_fail, erl_flags}). + kill_if_fail, erl_flags, env}). %%%----------------------------------------------------------------- %%% @spec start(Node) -> Result @@ -85,7 +85,8 @@ start(Host, Node) -> %%% {startup_functions, StartupFunctions} | %%% {monitor_master, Monitor} | %%% {kill_if_fail, KillIfFail} | -%%% {erl_flags, ErlangFlags} +%%% {erl_flags, ErlangFlags} | +%%% {env, [{EnvVar,Value}]} %%% Username = string() %%% Password = string() %%% BootTimeout = integer() @@ -99,6 +100,8 @@ start(Host, Node) -> %%% Monitor = bool() %%% KillIfFail = bool() %%% ErlangFlags = string() +%%% EnvVar = string() +%%% Value = string() %%% Result = {ok, NodeName} | {error, already_started, NodeName} | %%% {error, started_not_connected, NodeName} | %%% {error, boot_timeout, NodeName} | @@ -152,6 +155,9 @@ start(Host, Node) -> %%% <p>Option <code>erlang_flags</code> specifies, which flags will be added %%% to the parameters of the <code>erl</code> executable.</p> %%% +%%% <p>Option <code>env</code> specifies a list of environment variables +%%% that will extended the environment.</p> +%%% %%% <p>Special return values are: %%% <list> %%% <item><code>{error, already_started, NodeName}</code> - if the node with @@ -233,10 +239,12 @@ fetch_options(Options) -> Monitor = get_option_value(monitor_master, Options, false), KillIfFail = get_option_value(kill_if_fail, Options, true), ErlFlags = get_option_value(erl_flags, Options, []), + EnvVars = get_option_value(env, Options, []), #options{username=UserName, password=Password, boot_timeout=BootTimeout, init_timeout=InitTimeout, startup_timeout=StartupTimeout, startup_functions=StartupFunctions, - monitor_master=Monitor, kill_if_fail=KillIfFail, erl_flags=ErlFlags}. + monitor_master=Monitor, kill_if_fail=KillIfFail, + erl_flags=ErlFlags, env=EnvVars}. % send a message when slave node is started % @hidden @@ -306,11 +314,19 @@ do_start(Host, Node, Options) -> true-> spawn_remote_node(Host, Node, Options) end, + BootTimeout = Options#options.boot_timeout, InitTimeout = Options#options.init_timeout, StartupTimeout = Options#options.startup_timeout, Result = case wait_for_node_alive(ENode, BootTimeout) of pong-> + case test_server:is_cover() of + true -> + MainCoverNode = cover:get_main_node(), + rpc:call(MainCoverNode,cover,start,[ENode]); + false -> + ok + end, call_functions(ENode, Functions2), receive {node_started, ENode}-> @@ -365,9 +381,9 @@ get_cmd(Node, Flags) -> % spawn node locally spawn_local_node(Node, Options) -> - ErlFlags = Options#options.erl_flags, + #options{env=Env,erl_flags=ErlFlags} = Options, Cmd = get_cmd(Node, ErlFlags), - open_port({spawn, Cmd}, [stream]). + open_port({spawn, Cmd}, [stream,{env,Env}]). % start crypto and ssh if not yet started check_for_ssh_running() -> @@ -386,9 +402,10 @@ check_for_ssh_running() -> % spawn node remotely spawn_remote_node(Host, Node, Options) -> - Username = Options#options.username, - Password = Options#options.password, - ErlFlags = Options#options.erl_flags, + #options{username=Username, + password=Password, + erl_flags=ErlFlags, + env=Env} = Options, SSHOptions = case {Username, Password} of {[], []}-> []; @@ -400,8 +417,17 @@ spawn_remote_node(Host, Node, Options) -> check_for_ssh_running(), {ok, SSHConnRef} = ssh:connect(atom_to_list(Host), 22, SSHOptions), {ok, SSHChannelId} = ssh_connection:session_channel(SSHConnRef, infinity), + ssh_setenv(SSHConnRef, SSHChannelId, Env), ssh_connection:exec(SSHConnRef, SSHChannelId, get_cmd(Node, ErlFlags), infinity). + +ssh_setenv(SSHConnRef, SSHChannelId, [{Var, Value} | Vars]) + when is_list(Var), is_list(Value) -> + success = ssh_connection:setenv(SSHConnRef, SSHChannelId, + Var, Value, infinity), + ssh_setenv(SSHConnRef, SSHChannelId, Vars); +ssh_setenv(_SSHConnRef, _SSHChannelId, []) -> ok. + % call functions on a remote Erlang node call_functions(_Node, []) -> ok; @@ -423,6 +449,13 @@ wait_for_node_alive(Node, N) -> % call init:stop on a remote node do_stop(ENode) -> + case test_server:is_cover() of + true -> + MainCoverNode = cover:get_main_node(), + rpc:call(MainCoverNode,cover,flush,[ENode]); + false -> + ok + end, spawn(ENode, init, stop, []), wait_for_node_dead(ENode, 5). diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl index 8fe63e8ed1..71038bd4f4 100644 --- a/lib/common_test/src/ct_snmp.erl +++ b/lib/common_test/src/ct_snmp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. 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 @@ -39,7 +39,7 @@ %%% %%% 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 +%%% {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 @@ -130,7 +130,7 @@ %%% @type agent_config() = {Item, Value} %%% @type user_name() = atom() %%% @type usm_user_name() = string() -%%% @type usm_config() = string() +%%% @type usm_config() = {Item, Value} %%% @type call_back_module() = atom() %%% @type user_data() = term() %%% @type oids() = [oid()] @@ -157,8 +157,9 @@ %%% 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]). + unregister_users/1, unregister_users/2, unregister_agents/1, + unregister_agents/2, unregister_usm_users/1, unregister_usm_users/2, + load_mibs/1, unload_mibs/1]). %% Manager values -define(CT_SNMP_LOG_FILE, "ct_snmp_set.log"). @@ -250,10 +251,8 @@ stop(Config) -> %%% %%% @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), + [Uid | _] = agent_conf(Agent, MgrAgentConfName), + {ok, SnmpReply, _} = snmpm:sync_get2(Uid, target_name(Agent), Oids), SnmpReply. %%% @spec get_next_values(Agent, Oids, MgrAgentConfName) -> SnmpReply @@ -265,10 +264,8 @@ get_values(Agent, Oids, MgrAgentConfName) -> %%% %%% @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), + [Uid | _] = agent_conf(Agent, MgrAgentConfName), + {ok, SnmpReply, _} = snmpm:sync_get_next2(Uid, target_name(Agent), Oids), SnmpReply. %%% @spec set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -> SnmpReply @@ -282,13 +279,11 @@ get_next_values(Agent, Oids, MgrAgentConfName) -> %%% @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), + [Uid | _] = 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), + TargetName = target_name(Agent), + {ok, SnmpGetReply, _} = snmpm:sync_get2(Uid, TargetName, Oids), + {ok, SnmpSetReply, _} = snmpm:sync_set2(Uid, TargetName, VarsAndVals), case SnmpSetReply of {noError, 0, _} when PrivDir /= false -> log(PrivDir, Agent, SnmpGetReply, VarsAndVals); @@ -328,12 +323,23 @@ set_info(Config) -> %%% Reason = term() %%% %%% @doc Register the manager entity (=user) responsible for specific agent(s). -%%% Corresponds to making an entry in users.conf +%%% Corresponds to making an entry in users.conf. +%%% +%%% This function will try to register the given users, without +%%% checking if any of them already exist. In order to change an +%%% already registered user, the user must first be unregistered. register_users(MgrAgentConfName, Users) -> - {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), - NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users, Users}), - ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), - setup_users(Users). + case setup_users(Users) of + ok -> + SnmpVals = ct:get_config(MgrAgentConfName), + OldUsers = ct:get_config({MgrAgentConfName,users},[]), + NewSnmpVals = lists:keystore(users, 1, SnmpVals, + {users, Users ++ OldUsers}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok; + Error -> + Error + end. %%% @spec register_agents(MgrAgentConfName, ManagedAgents) -> ok | {error, Reason} %%% @@ -343,12 +349,24 @@ register_users(MgrAgentConfName, Users) -> %%% %%% @doc Explicitly instruct the manager to handle this agent. %%% Corresponds to making an entry in agents.conf +%%% +%%% This function will try to register the given managed agents, +%%% without checking if any of them already exist. In order to change +%%% an already registered managed agent, the agent must first be +%%% unregistered. register_agents(MgrAgentConfName, ManagedAgents) -> - {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), - NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, - {managed_agents, ManagedAgents}), - ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), - setup_managed_agents(ManagedAgents). + case setup_managed_agents(MgrAgentConfName,ManagedAgents) of + ok -> + SnmpVals = ct:get_config(MgrAgentConfName), + OldAgents = ct:get_config({MgrAgentConfName,managed_agents},[]), + NewSnmpVals = lists:keystore(managed_agents, 1, SnmpVals, + {managed_agents, + ManagedAgents ++ OldAgents}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok; + Error -> + Error + end. %%% @spec register_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason} %%% @@ -358,60 +376,115 @@ register_agents(MgrAgentConfName, ManagedAgents) -> %%% %%% @doc Explicitly instruct the manager to handle this USM user. %%% Corresponds to making an entry in usm.conf +%%% +%%% This function will try to register the given users, without +%%% checking if any of them already exist. In order to change an +%%% already registered user, the user must first be unregistered. register_usm_users(MgrAgentConfName, UsmUsers) -> - {snmp, SnmpVals} = ct:get_config(MgrAgentConfName), - NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {usm_users, UsmUsers}), - ct_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), - setup_usm_users(UsmUsers, EngineID). + case setup_usm_users(UsmUsers, EngineID) of + ok -> + SnmpVals = ct:get_config(MgrAgentConfName), + OldUsmUsers = ct:get_config({MgrAgentConfName,usm_users},[]), + NewSnmpVals = lists:keystore(usm_users, 1, SnmpVals, + {usm_users, UsmUsers ++ OldUsmUsers}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok; + Error -> + Error + end. -%%% @spec unregister_users(MgrAgentConfName) -> ok | {error, Reason} +%%% @spec unregister_users(MgrAgentConfName) -> ok %%% %%% MgrAgentConfName = atom() %%% Reason = term() %%% -%%% @doc Removes information added when calling register_users/2. +%%% @doc Unregister all users. 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_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), - takedown_users(Users). + Users = [Id || {Id,_} <- ct:get_config({MgrAgentConfName, users},[])], + unregister_users(MgrAgentConfName,Users). -%%% @spec unregister_agents(MgrAgentConfName) -> ok | {error, Reason} +%%% @spec unregister_users(MgrAgentConfName,Users) -> ok %%% %%% MgrAgentConfName = atom() +%%% Users = [user_name()] %%% Reason = term() %%% -%%% @doc Removes information added when calling register_agents/2. +%%% @doc Unregister the given users. +unregister_users(MgrAgentConfName,Users) -> + takedown_users(Users), + SnmpVals = ct:get_config(MgrAgentConfName), + AllUsers = ct:get_config({MgrAgentConfName, users},[]), + RemainingUsers = lists:filter(fun({Id,_}) -> + not lists:member(Id,Users) + end, + AllUsers), + NewSnmpVals = lists:keyreplace(users, 1, SnmpVals, {users,RemainingUsers}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok. + +%%% @spec unregister_agents(MgrAgentConfName) -> ok +%%% +%%% MgrAgentConfName = atom() +%%% Reason = term() +%%% +%%% @doc Unregister all managed agents. 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_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), - takedown_managed_agents(ManagedAgents). + ManagedAgents = [AgentName || + {AgentName, _} <- + ct:get_config({MgrAgentConfName,managed_agents},[])], + unregister_agents(MgrAgentConfName,ManagedAgents). +%%% @spec unregister_agents(MgrAgentConfName,ManagedAgents) -> ok +%%% +%%% MgrAgentConfName = atom() +%%% ManagedAgents = [agent_name()] +%%% Reason = term() +%%% +%%% @doc Unregister the given managed agents. +unregister_agents(MgrAgentConfName,ManagedAgents) -> + takedown_managed_agents(MgrAgentConfName, ManagedAgents), + SnmpVals = ct:get_config(MgrAgentConfName), + AllAgents = ct:get_config({MgrAgentConfName,managed_agents},[]), + RemainingAgents = lists:filter(fun({Name,_}) -> + not lists:member(Name,ManagedAgents) + end, + AllAgents), + NewSnmpVals = lists:keyreplace(managed_agents, 1, SnmpVals, + {managed_agents,RemainingAgents}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok. -%%% @spec update_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason} +%%% @spec unregister_usm_users(MgrAgentConfName) -> ok %%% %%% 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_config:update_config(MgrAgentConfName, {snmp, NewSnmpVals}), +%%% @doc Unregister all usm users. +unregister_usm_users(MgrAgentConfName) -> + UsmUsers = [Id || {Id,_} <- ct:get_config({MgrAgentConfName, usm_users},[])], + unregister_usm_users(MgrAgentConfName,UsmUsers). + +%%% @spec unregister_usm_users(MgrAgentConfName,UsmUsers) -> ok +%%% +%%% MgrAgentConfName = atom() +%%% UsmUsers = [usm_user_name()] +%%% Reason = term() +%%% +%%% @doc Unregister the given usm users. +unregister_usm_users(MgrAgentConfName,UsmUsers) -> EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), - do_update_usm_users(UsmUsers, EngineID). + takedown_usm_users(UsmUsers,EngineID), + SnmpVals = ct:get_config(MgrAgentConfName), + AllUsmUsers = ct:get_config({MgrAgentConfName, usm_users},[]), + RemainingUsmUsers = lists:filter(fun({Id,_}) -> + not lists:member(Id,UsmUsers) + end, + AllUsmUsers), + NewSnmpVals = lists:keyreplace(usm_users, 1, SnmpVals, + {usm_users,RemainingUsmUsers}), + ct_config:update_config(MgrAgentConfName, NewSnmpVals), + ok. %%% @spec load_mibs(Mibs) -> ok | {error, Reason} %%% @@ -423,6 +496,15 @@ update_usm_users(MgrAgentConfName, UsmUsers) -> load_mibs(Mibs) -> snmpa:load_mibs(snmp_master_agent, Mibs). +%%% @spec unload_mibs(Mibs) -> ok | {error, Reason} +%%% +%%% Mibs = [MibName] +%%% MibName = string() +%%% Reason = term() +%%% +%%% @doc Unload the mibs from the agent 'snmp_master_agent'. +unload_mibs(Mibs) -> + snmpa:unload_mibs(snmp_master_agent, Mibs). %%%======================================================================== %%% Internal functions @@ -486,9 +568,8 @@ setup_agent(true, AgentConfName, SnmpConfName, 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), + NotifType, SecType, Passwd, + AgentEngineID, AgentMaxMsgSize), override_default_configuration(Config, AgentConfName), @@ -497,7 +578,8 @@ setup_agent(true, AgentConfName, SnmpConfName, {verbosity, trace}]}, {agent_type, master}, {agent_verbosity, trace}, - {net_if, [{verbosity, trace}]}], + {net_if, [{verbosity, trace}]}, + {versions, Vsns}], ct:get_config({SnmpConfName,agent})), application:set_env(snmp, agent, SnmpEnv). %%%--------------------------------------------------------------------------- @@ -535,65 +617,61 @@ manager_register(true, MgrAgentConfName) -> setup_usm_users(UsmUsers, EngineID), setup_users(Users), - setup_managed_agents(Agents). + setup_managed_agents(MgrAgentConfName,Agents). %%%--------------------------------------------------------------------------- setup_users(Users) -> - lists:foreach(fun({Id, [Module, Data]}) -> - snmpm:register_user(Id, Module, Data) - end, Users). + while_ok(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_managed_agents(AgentConfName,Agents) -> + Fun = + fun({AgentName, [Uid, AgentIp, AgentUdpPort, AgentConf0]}) -> + 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, + AgentConf = + case lists:keymember(engine_id,1,AgentConf0) of + true -> + AgentConf0; + false -> + DefaultEngineID = + ct:get_config({AgentConfName,agent_engine_id}, + ?AGENT_ENGINE_ID), + [{engine_id,DefaultEngineID}|AgentConf0] + end, + snmpm:register_agent(Uid, target_name(AgentName), + [{address,NewAgentIp},{port,AgentUdpPort} | + AgentConf]) + end, + while_ok(Fun,Agents). %%%--------------------------------------------------------------------------- setup_usm_users(UsmUsers, EngineID)-> - lists:foreach(fun({UsmUser, Conf}) -> - snmpm:register_usm_user(EngineID, UsmUser, Conf) - end, UsmUsers). + while_ok(fun({UsmUser, Conf}) -> + snmpm:register_usm_user(EngineID, UsmUser, Conf) + end, UsmUsers). %%%--------------------------------------------------------------------------- takedown_users(Users) -> - lists:foreach(fun({Id}) -> + 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. +takedown_managed_agents(MgrAgentConfName,ManagedAgents) -> + lists:foreach(fun(AgentName) -> + [Uid | _] = agent_conf(AgentName, MgrAgentConfName), + snmpm:unregister_agent(Uid, target_name(AgentName)) + end, ManagedAgents). %%%--------------------------------------------------------------------------- -do_update_usm_users(UsmUsers, EngineID) -> - lists:foreach(fun({UsmUser, {Item, Val}}) -> - snmpm:update_usm_user_info(EngineID, UsmUser, - Item, Val) - end, UsmUsers). +takedown_usm_users(UsmUsers, EngineID) -> + lists:foreach(fun(Id) -> + snmpm:unregister_usm_user(EngineID, Id) + end, UsmUsers). %%%--------------------------------------------------------------------------- log(PrivDir, Agent, {_, _, Varbinds}, NewVarsAndVals) -> @@ -657,7 +735,7 @@ override_contexts(Config, {data_dir_file, File}) -> override_contexts(Config, ContextInfo); override_contexts(Config, Contexts) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"context.conf"), file:delete(File), snmp_config:write_agent_context_config(Dir, "", Contexts). @@ -673,7 +751,7 @@ override_sysinfo(Config, {data_dir_file, File}) -> override_sysinfo(Config, SysInfo); override_sysinfo(Config, SysInfo) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"standard.conf"), file:delete(File), snmp_config:write_agent_standard_config(Dir, "", SysInfo). @@ -688,7 +766,7 @@ override_target_address(Config, {data_dir_file, File}) -> override_target_address(Config, TargetAddressConf); override_target_address(Config, TargetAddressConf) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"target_addr.conf"), file:delete(File), snmp_config:write_agent_target_addr_config(Dir, "", TargetAddressConf). @@ -704,7 +782,7 @@ override_target_params(Config, {data_dir_file, File}) -> override_target_params(Config, TargetParamsConf); override_target_params(Config, TargetParamsConf) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"target_params.conf"), file:delete(File), snmp_config:write_agent_target_params_config(Dir, "", TargetParamsConf). @@ -719,7 +797,7 @@ override_notify(Config, {data_dir_file, File}) -> override_notify(Config, NotifyConf); override_notify(Config, NotifyConf) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"notify.conf"), file:delete(File), snmp_config:write_agent_notify_config(Dir, "", NotifyConf). @@ -734,7 +812,7 @@ override_usm(Config, {data_dir_file, File}) -> override_usm(Config, UsmConf); override_usm(Config, UsmConf) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"usm.conf"), file:delete(File), snmp_config:write_agent_usm_config(Dir, "", UsmConf). @@ -749,7 +827,7 @@ override_community(Config, {data_dir_file, File}) -> override_community(Config, CommunityConf); override_community(Config, CommunityConf) -> - Dir = ?config(priv_dir, Config), + Dir = filename:join(?config(priv_dir, Config),"conf"), File = filename:join(Dir,"community.conf"), file:delete(File), snmp_config:write_agent_community_config(Dir, "", CommunityConf). @@ -765,7 +843,20 @@ override_vacm(Config, {data_dir_file, File}) -> override_vacm(Config, VacmConf); override_vacm(Config, VacmConf) -> - Dir = ?config(priv_dir, Config), - File = filename:join(Dir,"vacm.conf"), + Dir = filename:join(?config(priv_dir, Config),"conf"), + File = filename:join(Dir,"vacm.conf"), file:delete(File), snmp_config:write_agent_vacm_config(Dir, "", VacmConf). + +%%%--------------------------------------------------------------------------- + +target_name(Agent) -> + atom_to_list(Agent). + +while_ok(Fun,[H|T]) -> + case Fun(H) of + ok -> while_ok(Fun,T); + Error -> Error + end; +while_ok(_Fun,[]) -> + ok. diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index 5ce095e38e..202d8f9373 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -903,6 +903,8 @@ handle_data(logdir,Node,Dir,Spec) -> [{Node,ref2dir(Dir,Spec)}]; handle_data(cover,Node,File,Spec) -> [{Node,get_absfile(File,Spec)}]; +handle_data(cover_stop,Node,Stop,_Spec) -> + [{Node,Stop}]; handle_data(include,Node,Dirs=[D|_],Spec) when is_list(D) -> [{Node,ref2dir(Dir,Spec)} || Dir <- Dirs]; handle_data(include,Node,Dir=[Ch|_],Spec) when is_integer(Ch) -> @@ -1262,6 +1264,8 @@ valid_terms() -> {node,3}, {cover,2}, {cover,3}, + {cover_stop,2}, + {cover_stop,3}, {config,2}, {config,3}, {config,4}, diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 196b5e46d0..c9c6514fa4 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -38,6 +38,7 @@ verbosity=[], silent_connections=[], cover=[], + cover_stop=[], config=[], userconfig=[], event_handler=[], diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl index 77f57c6195..78ae70f37e 100644 --- a/lib/common_test/src/cth_log_redirect.erl +++ b/lib/common_test/src/cth_log_redirect.erl @@ -54,7 +54,7 @@ post_init_per_group(_Group, _Config, Result, State) -> post_end_per_testcase(_TC, _Config, Result, State) -> %% Make sure that the event queue is flushed %% before ending this test case. - gen_event:call(error_logger, ?MODULE, flush), + gen_event:call(error_logger, ?MODULE, flush, 300000), {Result, State}. pre_end_per_group(Group, Config, {ct_log, Group}) -> |