1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2021. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(snmp_agent_test_lib). 22 23 24-export([ 25 start_v1_agent/1, start_v1_agent/2, 26 start_v2_agent/1, start_v2_agent/2, 27 start_v3_agent/1, start_v3_agent/2, 28 start_bilingual_agent/1, start_bilingual_agent/2, 29 start_mt_agent/1, start_mt_agent/2, start_mt_agent/3, 30 stop_agent/1, 31 32 %% start_sup/0, stop_sup/2, 33 start_subagent/3, stop_subagent/1, 34 start_sub_sup/1, start_sub_sup/2, 35 36 start_node/1, stop_node/1, 37 38 load_master/1, load_master_std/1, unload_master/1, 39 loaded_mibs/0, unload_mibs/1, 40 41 get_req/2, get_next_req/1, 42 43 config/5, config/6, 44 delete_files/1, 45 copy_file/2, 46 update_usm/2, 47 update_usm_mgr/2, rewrite_usm_mgr/3, reset_usm_mgr/1, 48 update_community/2, 49 update_vacm/2, 50 write_community_conf/2, 51 write_target_addr_conf/2, write_target_addr_conf/4, 52 rewrite_target_addr_conf/2, reset_target_addr_conf/1, 53 write_target_params_conf/2, rewrite_target_params_conf/3, 54 reset_target_params_conf/1, 55 write_notify_conf/1, write_view_conf/1, 56 57 display_memory_usage/0, 58 59 init_all/1, finish_all/1, 60 init_case/1, 61 try_test/2, try_test/3, try_test/4, 62 expect/3, expect/4, expect/5, expect/7, 63 64 regs/0, 65 rpc/3 66 ]). 67 68%% Internal exports 69-export([tc_wait/5, tc_run/4]). 70 71-include_lib("kernel/include/file.hrl"). 72-include_lib("common_test/include/ct.hrl"). 73-include("snmp_test_lib.hrl"). 74-define(SNMP_USE_V3, true). 75-include_lib("snmp/include/snmp_types.hrl"). 76 77-define(TRAP_UDP, 5000). 78 79-define(v1_2(V1,V2), 80 case get(vsn) of 81 v1 -> V1; 82 _ -> V2 83 end). 84 85-define(v1_2_3(V1,V2,V3), 86 case get(vsn) of 87 v1 -> V1; 88 v2 -> V2; 89 _ -> V3 90 end). 91 92 93%%%----------------------------------------------------------------- 94%%% The test case structure is as follows: 95%%% 96%%% init_all - starts mnesia, 97%%% 98%%% init_v1 - starts agent 99%%% simple 100%%% big - e.g. starts/stops subagent, load/unloads mibs 101%%% init_mul 102%%% mul_get 103%%% mul_set 104%%% <etc> 105%%% finish_mul 106%%% <etc> 107%%% finish_v1 108%%% 109%%% init_v2 - starts agent 110%%% finish_v2 111%%% 112%%% init_bilingual - starts agent 113%%% finish_bilingual 114%%% 115%%% finish_all 116%%% 117%%% There is still one problem with these testsuites. If one test 118%%% fails, it may not be possible to run some other cases, as it 119%%% may have e.g. created some row or loaded some table, that it 120%%% didn't undo (since it failed). 121%%%----------------------------------------------------------------- 122 123init_all(Config) when is_list(Config) -> 124 125 ?IPRINT("init_all -> entry with" 126 "~n Config: ~p" 127 "~n Nodes: ~p", [Config, nodes()]), 128 129 %% -- 130 %% Start nodes 131 %% 132 133 ?IPRINT("init_all -> start sub-agent node"), 134 ?line {ok, SaNode} = start_node(snmp_sa), 135 136 ?IPRINT("init_all -> start manager node"), 137 ?line {ok, MgrNode} = start_node(snmp_mgr), 138 139 140 %% -- 141 %% Create necessary files ( and dirs ) 142 %% 143 144 ?IPRINT("init_all -> lookup group top dir"), 145 GroupTopDir = ?config(snmp_group_top_dir, Config), 146 ?DBG("init_all -> GroupTopDir ~p", [GroupTopDir]), 147 148 ?IPRINT("init_all -> create agent dir"), 149 AgentDir = join(GroupTopDir, "agent/"), 150 ?line ok = file:make_dir(AgentDir), 151 ?DBG("init_all -> AgentDir ~p", [AgentDir]), 152 153 ?IPRINT("init_all -> create agent db dir"), 154 AgentDbDir = join(AgentDir, "db/"), 155 ?line ok = file:make_dir(AgentDbDir), 156 ?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]), 157 158 ?IPRINT("init_all -> create agent log dir"), 159 AgentLogDir = join(AgentDir, "log/"), 160 ?line ok = file:make_dir(AgentLogDir), 161 ?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]), 162 163 ?IPRINT("init_all -> create agent config dir"), 164 AgentConfDir = join(AgentDir, "conf/"), 165 ?line ok = file:make_dir(AgentConfDir), 166 ?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]), 167 168 ?IPRINT("init_all -> create manager dir"), 169 MgrDir = join(GroupTopDir, "mgr/"), 170 ?line ok = file:make_dir(MgrDir), 171 ?DBG("init_all -> MgrDir ~p", [MgrDir]), 172 173 ?IPRINT("init_all -> create sub-agent dir"), 174 SaDir = join(GroupTopDir, "sa/"), 175 ?line ok = file:make_dir(SaDir), 176 ?DBG("init_all -> SaDir ~p", [SaDir]), 177 178 ?IPRINT("init_all -> create sub-agent db dir"), 179 SaDbDir = join(SaDir, "db/"), 180 ?line ok = file:make_dir(SaDbDir), 181 ?DBG("init_all -> SaDbDir ~p", [SaDbDir]), 182 183 %% MibDir = ?config(mib_dir, Config), 184 %% ?DBG("init_all -> MibDir ~p", [DataDir]), 185 186 187 %% -- 188 %% Start and initiate mnesia 189 %% 190 191 ?IPRINT("init_all -> load mnesia application (local)"), 192 ?line ok = application:load(mnesia), 193 194 ?IPRINT("init_all -> load application mnesia on node ~p", [SaNode]), 195 ?line ok = rpc:call(SaNode, application, load, [mnesia]), 196 197 ?IPRINT("init_all -> application mnesia (local): set_env dir"), 198 ?line application_controller:set_env(mnesia, dir, 199 join(AgentDbDir, "Mnesia1")), 200 201 ?IPRINT("init_all -> application mnesia: set_env dir on node ~p", [SaNode]), 202 ?line rpc:call(SaNode, application_controller, set_env, 203 [mnesia, dir, join(SaDir, "Mnesia2")]), 204 205 ?IPRINT("init_all -> create mnesia schema"), 206 ?line ok = mnesia:create_schema([SaNode, node()]), 207 208 ?IPRINT("init_all -> start application mnesia (local)"), 209 ?line ok = application:start(mnesia), 210 211 ?IPRINT("init_all -> start application mnesia on ~p", [SaNode]), 212 ?line ok = rpc:call(SaNode, application, start, [mnesia]), 213 214 ?IPRINT("init_all -> get localhost"), 215 Ip = ?LOCALHOST(), 216 217 ?IPRINT("init_all -> done when" 218 "~n Nodes: ~p", [nodes()]), 219 [{snmp_sa, SaNode}, 220 {snmp_mgr, MgrNode}, 221 {snmp_master, node()}, 222 {agent_dir, AgentDir ++ "/"}, 223 {agent_db_dir, AgentDbDir ++ "/"}, 224 {agent_log_dir, AgentLogDir ++ "/"}, 225 {agent_conf_dir, AgentConfDir ++ "/"}, 226 {sa_dir, SaDir ++ "/"}, 227 {sa_db_dir, SaDbDir ++ "/"}, 228 {mgr_dir, MgrDir ++ "/"}, 229 %% {mib_dir, DataDir}, 230 {ip, Ip} | 231 Config]. 232 233 234finish_all(Config) when is_list(Config) -> 235 236 ?IPRINT("finish_all -> entry with" 237 "~n Config: ~p" 238 "~n Nodes: ~p", [Config, nodes()]), 239 240 SaNode = ?config(snmp_sa, Config), 241 MgrNode = ?config(snmp_mgr, Config), 242 243 ?IPRINT("finish_all -> stop sub-agent node ~p", [SaNode]), 244 stop_node(SaNode), 245 246 ?IPRINT("finish_all -> stop manager node ~p", [MgrNode]), 247 stop_node(MgrNode), 248 249 ?IPRINT("finish_all -> stop mnesia application"), 250 application:stop(mnesia), 251 252 ?IPRINT("finish_all -> unload mnesia application"), 253 application:unload(mnesia), 254 255 ?IPRINT("finish_all -> stop when" 256 "~n Nodes: ~p", [nodes()]), 257 ok. 258 259 260%% --- This one *must* be run first in each case --- 261 262init_case(Config) when is_list(Config) -> 263 264 ?DBG("init_case -> entry with" 265 "~n Config: ~p", [Config]), 266 267 SaNode = ?config(snmp_sa, Config), 268 MgrNode = ?config(snmp_mgr, Config), 269 MasterNode = ?config(snmp_master, Config), 270 %% MasterNode = node(), 271 IpFamily = proplists:get_value(ipfamily, Config, inet), 272 273 SaHost = ?HOSTNAME(SaNode), 274 MgrHost = ?HOSTNAME(MgrNode), 275 MasterHost = ?HOSTNAME(MasterNode), 276 {ok, MasterIP} = ?LIB:which_host_ip(MasterHost, IpFamily), 277 {ok, MIP} = ?LIB:which_host_ip(MgrHost, IpFamily), 278 {ok, SIP} = ?LIB:which_host_ip(SaHost, IpFamily), 279 280 ?IPRINT("init_case -> " 281 "~n SaHost: ~p" 282 "~n MgrHost: ~p" 283 "~n MasterHost: ~p" 284 "~n MasterIP: ~p" 285 "~n MIP: ~p" 286 "~n SIP: ~p", 287 [SaHost, MgrHost, MasterHost, MasterIP, MIP, SIP]), 288 289 put(mgr_node, MgrNode), 290 put(sa_node, SaNode), 291 put(master_node, MasterNode), 292 put(sa_host, SaHost), 293 put(mgr_host, MgrHost), 294 put(master_host, MasterHost), 295 put(mip, tuple_to_list(MIP)), 296 put(masterip, tuple_to_list(MasterIP)), 297 put(sip, tuple_to_list(SIP)), 298 put(ipfamily, IpFamily), 299 300 MibDir = ?config(mib_dir, Config), 301 put(mib_dir, MibDir), 302 StdM = join(code:priv_dir(snmp), "mibs") ++ "/", 303 put(std_mib_dir, StdM), 304 305 MgrDir = ?config(mgr_dir, Config), 306 put(mgr_dir, MgrDir), 307 308 put(vsn, ?config(vsn, Config)), 309 310 ?IPRINT("init_case -> done with" 311 "~n MasterNode: ~p" 312 "~n SaNode: ~p" 313 "~n MgrNode: ~p" 314 "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), 315 316 {SaNode, MgrNode, MibDir}. 317 318 319%%%-------------------------------------------------- 320%%% Used to test the standard mib with our 321%%% configuration. 322%%%-------------------------------------------------- 323 324try_test(TcRunMod, TcRunFunc) -> 325 try_test(TcRunMod, TcRunFunc, []). 326 327try_test(TcRunMod, TcRunFunc, TcRunArgs) -> 328 try_test(TcRunMod, TcRunFunc, TcRunArgs, []). 329 330try_test(TcRunMod, TcRunFunc, TcRunArgs, TcRunOpts) -> 331 Node = get(mgr_node), 332 Mod = ?MODULE, 333 Func = tc_run, 334 Args = [TcRunMod, TcRunFunc, TcRunArgs, TcRunOpts], 335 tc_try(Node, Mod, Func, Args). 336 337%% We spawn a test case runner process on the manager node. 338%% The assumption is that the manager shall do something, but 339%% not all test cases have the manager perform actions. 340%% In some cases we make a rpc call back to the agent node directly 341%% and call something in the agent... (for example the info_test 342%% test case). 343%% We should use link (instead of monitor) in order for the test case 344%% timeout cleanup (kills) should have effect on the test case runner 345%% process as well. 346 347tc_try(N, M, F, A) -> 348 ?IPRINT("tc_try -> entry with" 349 "~n N: ~p" 350 "~n M: ~p" 351 "~n F: ~p" 352 "~n A: ~p" 353 "~n when" 354 "~n get(): ~p" 355 "~n", [N, 356 M, F, A, 357 get()]), 358 case net_adm:ping(N) of 359 pong -> 360 ?IPRINT("tc_try -> ~p still running - start runner~n", [N]), 361 OldFlag = trap_exit(true), % Make sure we catch it 362 Runner = spawn_link(N, ?MODULE, tc_wait, [self(), get(), M, F, A]), 363 await_tc_runner_started(Runner, OldFlag), 364 await_tc_runner_done(Runner, OldFlag); 365 pang -> 366 ?WPRINT("tc_try -> ~p *not* running~n", [N]), 367 skip({node_not_running, N}) 368 end. 369 370await_tc_runner_started(Runner, OldFlag) -> 371 ?IPRINT("await tc-runner (~p) start ack~n", [Runner]), 372 receive 373 {'EXIT', Runner, Reason} -> 374 ?EPRINT("TC runner start failed: " 375 "~n ~p~n", [Reason]), 376 exit({tc_runner_start_failed, Reason}); 377 {tc_runner_started, Runner} -> 378 ?IPRINT("TC runner start acknowledged~n"), 379 ok 380 after 10000 -> %% We should *really* not have to wait this long, but... 381 trap_exit(OldFlag), 382 unlink_and_flush_exit(Runner), 383 RunnerInfo = ?PINFO(Runner), 384 ?EPRINT("TC runner start timeout: " 385 "~n ~p", [RunnerInfo]), 386 %% If we don't get a start ack within 10 seconds, we are f*ed 387 exit(Runner, kill), 388 exit({tc_runner_start, timeout, RunnerInfo}) 389 end. 390 391await_tc_runner_done(Runner, OldFlag) -> 392 receive 393 {'EXIT', Runner, {udp_error, _} = Reason} -> 394 ?EPRINT("TC runner failed with an udp error: " 395 "~n Reason: ~p" 396 "~n", [Reason]), 397 skip([{reason, Reason}]); 398 399 {'EXIT', Runner, Reason} -> 400 %% This is not a normal (tc) failure (that is the clause below). 401 %% Instead the tc runner process crashed, for some reason. So 402 %% check if have got any system events, and if so, skip. 403 SysEvs = snmp_test_global_sys_monitor:events(), 404 if 405 (SysEvs =:= []) -> 406 ?EPRINT("TC runner failed: " 407 "~n ~p" 408 "~n", [Reason]), 409 exit({tc_runner_failed, Reason}); 410 true -> 411 ?WPRINT("TC runner failed when we got system events: " 412 "~n Reason: ~p" 413 "~n Sys Events: ~p" 414 "~n", [Reason, SysEvs]), 415 skip([{reason, Reason}, {system_events, SysEvs}]) 416 end; 417 {tc_runner_done, Runner, {'EXIT', {skip, Reason}}, Loc} -> 418 ?WPRINT("call -> done with skip: " 419 "~n Reason: ~p" 420 "~n Loc: ~p" 421 "~n", [Reason, Loc]), 422 trap_exit(OldFlag), 423 unlink_and_flush_exit(Runner), 424 put(test_server_loc, Loc), 425 skip(Reason); 426 {tc_runner_done, Runner, {'EXIT', Rn}, Loc} -> 427 ?EPRINT("call -> done with exit: " 428 "~n Rn: ~p" 429 "~n Loc: ~p" 430 "~n", [Rn, Loc]), 431 trap_exit(OldFlag), 432 unlink_and_flush_exit(Runner), 433 put(test_server_loc, Loc), 434 exit(Rn); 435 {tc_runner_done, Runner, Ret, _Loc} -> 436 ?IPRINT("call -> done:" 437 "~n Ret: ~p" 438 "~n Loc: ~p", [Ret, _Loc]), 439 trap_exit(OldFlag), 440 unlink_and_flush_exit(Runner), 441 case Ret of 442 {error, Reason} -> 443 %% Any failures while we have system events are skipped 444 SysEvs = snmp_test_global_sys_monitor:events(), 445 if 446 (SysEvs =:= []) -> 447 ?EPRINT("TC failure: " 448 "~n ~p" 449 "~n", [Reason]), 450 exit(Reason); 451 true -> 452 ?WPRINT("TC failure when we got system events: " 453 "~n Reason: ~p" 454 "~n Sys Events: ~p" 455 "~n", [Reason, SysEvs]), 456 skip([{reason, Reason}, {system_events, SysEvs}]) 457 end; 458 {skip, Reason} -> 459 skip(Reason); 460 OK -> 461 OK 462 end 463 end. 464 465trap_exit(Flag) when is_boolean(Flag) -> 466 erlang:process_flag(trap_exit, Flag). 467 468unlink_and_flush_exit(Pid) -> 469 unlink(Pid), 470 receive 471 {'EXIT', Pid, _} -> 472 ok 473 after 0 -> 474 ok 475 end. 476 477tc_wait(From, Env, M, F, A) -> 478 ?IPRINT("tc_wait -> entry with" 479 "~n From: ~p" 480 "~n Env: ~p" 481 "~n M: ~p" 482 "~n F: ~p" 483 "~n A: ~p", [From, Env, M, F, A]), 484 From ! {tc_runner_started, self()}, 485 lists:foreach(fun({K,V}) -> put(K,V) end, Env), 486 ?IPRINT("tc_wait -> env set - now run tc~n"), 487 Res = (catch apply(M, F, A)), 488 ?IPRINT("tc_wait -> tc run done: " 489 "~n ~p" 490 "~n", [Res]), 491 From ! {tc_runner_done, self(), Res, get(test_server_loc)}, 492 %% The point of this is that in some cases we have seen that the 493 %% exit signal having been "passed on" to the CT, which consider any 494 %% exit a fail (even if its {'EXIT', ok}). 495 %% So, just to be on the safe side, convert an 'ok' to a 'normal'. 496 case Res of 497 ok -> 498 exit(normal); 499 {ok, _} -> 500 exit(normal); 501 _ -> 502 exit(Res) 503 end. 504 505tc_run(Mod, Func, Args, Opts) -> 506 ?IPRINT("tc_run -> entry with" 507 "~n Mod: ~p" 508 "~n Func: ~p" 509 "~n Args: ~p" 510 "~n Opts: ~p" 511 "~n", [Mod, Func, Args, Opts]), 512 (catch snmp_test_mgr:stop()), % If we had a running mgr from a failed case 513 M = get(mib_dir), 514 Dir = get(mgr_dir), 515 User = snmp_misc:get_option(user, Opts, "all-rights"), 516 SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), 517 EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), 518 CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), 519 Community = snmp_misc:get_option(community, Opts, "all-rights"), 520 ?DBG("tc_run -> start crypto app",[]), 521 _CryptoRes = ?CRYPTO_START(), 522 ?DBG("tc_run -> Crypto: ~p", [_CryptoRes]), 523 StdM = join(code:priv_dir(snmp), "mibs") ++ "/", 524 Vsn = get(vsn), 525 ?IPRINT("tc_run -> config:" 526 "~n M: ~p" 527 "~n Vsn: ~p" 528 "~n Dir: ~p" 529 "~n User: ~p" 530 "~n SecLevel: ~p" 531 "~n EngineID: ~p" 532 "~n CtxEngineID: ~p" 533 "~n Community: ~p" 534 "~n StdM: ~p" 535 "~n", [M,Vsn,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), 536 case snmp_test_mgr:start_link([%% {agent, snmp_test_lib:hostname()}, 537 {packet_server_debug, true}, 538 {debug, false}, 539 {agent, get(master_host)}, 540 {ipfamily, get(ipfamily)}, 541 {agent_udp, 4000}, 542 %% <SEP-TRANSPORTS> 543 %% First port is used to request replies 544 %% Second port is used for traps sent 545 %% by the agent. 546 %% {agent_udp, {4000, 4001}}, 547 %% </SEP-TRANSPORTS> 548 {trap_udp, 5000}, 549 {recbuf, 65535}, 550 quiet, 551 Vsn, 552 {community, Community}, 553 {user, User}, 554 {sec_level, SecLevel}, 555 {engine_id, EngineID}, 556 {context_engine_id, CtxEngineID}, 557 {dir, Dir}, 558 {mibs, mibs(StdM, M)}]) of 559 {ok, _Pid} -> 560 try apply(Mod, Func, Args) of 561 Res -> 562 (catch snmp_test_mgr:stop()), 563 Res 564 catch 565 C:{skip, Reason} -> 566 ?WPRINT("apply (~w-) skip detected: " 567 "~n ~p", [C, Reason]), 568 (catch snmp_test_mgr:stop()), 569 ?SKIP(Reason); 570 571 throw:{error, Reason} -> 572 tc_run_skip_sheck(Mod, Func, Args, Reason, throw); 573 574 exit:Reason -> 575 tc_run_skip_sheck(Mod, Func, Args, Reason, exit) 576 end; 577 578 {error, Reason} -> 579 ?EPRINT("Failed starting (test) manager: " 580 "~n ~p", [Reason]), 581 (catch snmp_test_mgr:stop()), 582 ?line ?FAIL({mgr_start_error, Reason}); 583 584 Err -> 585 ?EPRINT("Failed starting (test) manager: " 586 "~n ~p", [Err]), 587 (catch snmp_test_mgr:stop()), 588 ?line ?FAIL({mgr_start_failure, Err}) 589 end. 590 591%% We have hosts (mostly *very* slooow VMs) that 592%% can timeout anything. Since we are basically 593%% testing communication, we therefor must check 594%% for system events at every failure. Grrr! 595tc_run_skip_sheck(Mod, Func, Args, Reason, Cat) -> 596 SysEvs = snmp_test_global_sys_monitor:events(), 597 (catch snmp_test_mgr:stop()), 598 if 599 (SysEvs =:= []) -> 600 ?EPRINT("TC runner (~w-) failed: " 601 "~n ~p~n", [Cat, Reason]), 602 ?FAIL({apply_failed, {Mod, Func, Args}, Reason}); 603 true -> 604 ?WPRINT("apply (~w) catched " 605 "when we got system events: " 606 "~n Reason: ~p" 607 "~n Sys Events: ~p" 608 "~n", [Cat, Reason, SysEvs]), 609 ?SKIP([{category, Cat}, 610 {reason, Reason}, {system_events, SysEvs}]) 611 end. 612 613 614%% --------------------------------------------------------------- 615%% --- --- 616%% --- Start the agent --- 617%% --- --- 618%% --------------------------------------------------------------- 619 620start_v1_agent(Config) when is_list(Config) -> 621 start_agent(Config, [v1]). 622 623start_v1_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> 624 start_agent(Config, [v1], Opts). 625 626start_v2_agent(Config) when is_list(Config) -> 627 start_agent(Config, [v2]). 628 629start_v2_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> 630 start_agent(Config, [v2], Opts). 631 632start_v3_agent(Config) when is_list(Config) -> 633 start_agent(Config, [v3]). 634 635start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> 636 start_agent(Config, [v3], Opts). 637 638start_bilingual_agent(Config) when is_list(Config) -> 639 start_agent(Config, [v1,v2]). 640 641start_bilingual_agent(Config, Opts) 642 when is_list(Config) andalso is_list(Opts) -> 643 start_agent(Config, [v1,v2], Opts). 644 645start_mt_agent(Config) -> 646 start_mt_agent(Config, true, []). 647 648start_mt_agent(Config, MT) -> 649 start_mt_agent(Config, MT, []). 650 651start_mt_agent(Config, MT, Opts) 652 when is_list(Config) andalso 653 ((MT =:= true) orelse (MT =:= extended)) andalso 654 is_list(Opts) -> 655 start_agent(Config, [v2], [{multi_threaded, MT} | Opts]). 656 657start_agent(Config, Vsns) -> 658 start_agent(Config, Vsns, []). 659start_agent(Config, Vsns, Opts) -> 660 661 ?IPRINT("start_agent -> entry (~p) with" 662 "~n Config: ~p" 663 "~n Vsns: ~p" 664 "~n Opts: ~p", [node(), Config, Vsns, Opts]), 665 666 ?line AgentLogDir = ?config(agent_log_dir, Config), 667 ?line AgentConfDir = ?config(agent_conf_dir, Config), 668 ?line AgentDbDir = ?config(agent_db_dir, Config), 669 ?line SaNode = ?config(snmp_sa, Config), 670 ?line InetBackend = ?config(socket_create_opts, Config), 671 672 Env = app_agent_env_init( 673 [{versions, Vsns}, 674 {agent_type, master}, 675 {agent_verbosity, trace}, 676 {get_mechanism, snmp_agent_test_get}, 677 {db_dir, AgentDbDir}, 678 {audit_trail_log, [{type, read_write}, 679 {dir, AgentLogDir}, 680 {size, {10240, 10}}]}, 681 {config, [{dir, AgentConfDir}, 682 {force_load, false}, 683 {verbosity, trace}]}, 684 {local_db, [{repair, true}, 685 {verbosity, log}]}, 686 {mib_server, [{verbosity, log}]}, 687 {symbolic_store, [{verbosity, log}]}, 688 {note_store, [{verbosity, log}]}, 689 {net_if, [{verbosity, trace}, 690 {options, InetBackend}]}], 691 Opts), 692 693 694 process_flag(trap_exit,true), 695 696 ?IPRINT("start_agent -> try start snmp app supervisor", []), 697 {ok, AppSup} = snmp_app_sup:start_link(), 698 unlink(AppSup), 699 ?DBG("start_agent -> snmp app supervisor: ~p", [AppSup]), 700 701 ?IPRINT("start_agent -> try start master agent",[]), 702 ?line Sup = start_sup(Env), 703 ?line unlink(Sup), 704 ?DBG("start_agent -> snmp supervisor: ~p", [Sup]), 705 706 ?IPRINT("start_agent -> try (rpc) start sub agent on ~p", [SaNode]), 707 ?line SaDir = ?config(sa_dir, Config), 708 ?line {ok, Sub} = start_sub_sup(SaNode, SaDir), 709 ?DBG("start_agent -> done", []), 710 711 ?line [{snmp_app_sup, AppSup}, 712 {snmp_sup, {Sup, self()}}, 713 {snmp_sub, Sub} | Config]. 714 715 716app_agent_env_init(Env0, Opts) -> 717 ?DBG("app_agent_env_init -> unload snmp",[]), 718 ?line application:unload(snmp), 719 720 ?DBG("app_agent_env_init -> load snmp",[]), 721 ?line application:load(snmp), 722 723 ?DBG("app_agent_env_init -> " 724 "merge or maybe replace (snmp agent) app env",[]), 725 Env = add_or_maybe_merge_agent_env(Opts, Env0), 726 ?DBG("app_agent_env_init -> merged env: " 727 "~n ~p", [Env]), 728 729 %% We put it into the app environment just as 730 %% a precaution, since when starting normally, 731 %% this is where the environment is extracted from. 732 app_agent_set_env(Env), 733 Env. 734 735app_agent_set_env(Value) -> 736 application_controller:set_env(snmp, agent, Value). 737 738add_or_maybe_merge_agent_env([], Env) -> 739 ?DBG("merging agent env -> merged", []), 740 lists:keysort(1, Env); 741add_or_maybe_merge_agent_env([{Key, Value1}|Opts], Env) -> 742 ?DBG("merging agent env -> add, replace or merge ~p", [Key]), 743 case lists:keysearch(Key, 1, Env) of 744 {value, {Key, Value1}} -> 745 %% Identical, move on 746 ?DBG("merging agent env -> " 747 "no need to merge ~p - identical - keep: " 748 "~n ~p", [Key, Value1]), 749 add_or_maybe_merge_agent_env(Opts, Env); 750 {value, {Key, Value2}} -> 751 %% Another value, merge or replace 752 NewValue = merge_or_replace_agent_env(Key, Value1, Value2), 753 Env2 = lists:keyreplace(Key, 1, Env, {Key, NewValue}), 754 add_or_maybe_merge_agent_env(Opts, Env2); 755 false -> 756 ?DBG("merging agent env -> no old ~p to merge with - add: " 757 "~n ~p", [Key, Value1]), 758 add_or_maybe_merge_agent_env(Opts, [{Key, Value1}|Env]) 759 end. 760 761merge_or_replace_agent_env(versions, NewVersions, _OldVersions) -> 762 ?DBG("merging agent env -> versions replaced: ~p -> ~p", 763 [NewVersions, _OldVersions]), 764 NewVersions; 765merge_or_replace_agent_env(agent_type, NewType, _OldType) -> 766 ?DBG("merging agent env -> agent type replaced: ~p -> ~p", 767 [NewType, _OldType]), 768 NewType; 769merge_or_replace_agent_env(agent_verbosity, NewVerbosity, _OldVerbosity) -> 770 ?DBG("merging agent env -> agent verbosity replaced: ~p -> ~p", 771 [NewVerbosity, _OldVerbosity]), 772 NewVerbosity; 773merge_or_replace_agent_env(db_dir, NewDbDir, _OldDbDir) -> 774 ?DBG("merging agent env -> db-dir replaced: ~p -> ~p", 775 [NewDbDir, _OldDbDir]), 776 NewDbDir; 777merge_or_replace_agent_env(audit_trail_log, NewATL, OldATL) -> 778 merge_or_replace_agent_env_atl(NewATL, OldATL); 779merge_or_replace_agent_env(config, NewConfig, OldConfig) -> 780 merge_or_replace_agent_env_config(NewConfig, OldConfig); 781merge_or_replace_agent_env(local_db, NewLdb, OldLdb) -> 782 merge_or_replace_agent_env_ldb(NewLdb, OldLdb); 783merge_or_replace_agent_env(mib_storage, NewMst, OldMst) -> 784 merge_or_replace_agent_env_mib_storage(NewMst, OldMst); 785merge_or_replace_agent_env(mib_server, NewMibs, OldMibs) -> 786 merge_or_replace_agent_env_mib_server(NewMibs, OldMibs); 787merge_or_replace_agent_env(symbolic_store, NewSymStore, OldSymStore) -> 788 merge_or_replace_agent_env_symbolic_store(NewSymStore, OldSymStore); 789merge_or_replace_agent_env(note_store, NewNoteStore, OldNoteStore) -> 790 merge_or_replace_agent_env_note_store(NewNoteStore, OldNoteStore); 791merge_or_replace_agent_env(net_if, NewNetIf, OldNetIf) -> 792 merge_or_replace_agent_env_net_if(NewNetIf, OldNetIf); 793merge_or_replace_agent_env(Key, NewValue, OldValue) -> 794 ?FAIL({not_implemented_merge_or_replace, 795 Key, NewValue, OldValue}). 796 797merge_or_replace_agent_env_atl(New, Old) -> 798 ATL = merge_agent_options(New, Old), 799 ?DBG("merging agent env -> audit-trail-log merged: " 800 "~n ~p | ~p -> ~p", [New, Old, ATL]), 801 ATL. 802 803merge_or_replace_agent_env_config(New, Old) -> 804 Config = merge_agent_options(New, Old), 805 case lists:keymember(dir, 1, Config) of 806 true -> 807 ?DBG("merging agent env -> config merged: " 808 "~n ~p | ~p -> ~p", [New, Old, Config]), 809 Config; 810 false -> 811 ?FAIL({missing_mandatory_option, {config, dir}}) 812 end. 813 814merge_or_replace_agent_env_ldb(New, Old) -> 815 LDB = merge_agent_options(New, Old), 816 ?DBG("merging agent env -> local-db merged: " 817 "~n ~p | ~p -> ~p", [New, Old, LDB]), 818 LDB. 819 820merge_or_replace_agent_env_mib_storage(NewMibStorage, OldMibStorage) -> 821 %% Shall we merge or replace? 822 %% module is mandatory. We will only merge if NewModule is 823 %% equal to OldModule. 824 NewModule = 825 case lists:keysearch(module, 1, NewMibStorage) of 826 {value, {module, M}} -> 827 M; 828 false -> 829 ?FAIL({missing_mandatory_option, {mib_storage, module}}) 830 end, 831 case lists:keysearch(module, 1, OldMibStorage) of 832 {value, {module, NewModule}} -> 833 %% Same module => merge 834 %% Non-ex new options => remove 835 %% Ex new options and non-ex old options => replace 836 %% Otherwise merge 837 case lists:keysearch(options, 1, NewMibStorage) of 838 false -> 839 ?DBG("merging agent env -> " 840 "no mib-storage ~p merge needed - " 841 "no new options (= remove old options)", [NewModule]), 842 NewMibStorage; 843 {value, {options, NewOptions}} -> 844 case lists:keysearch(options, 1, OldMibStorage) of 845 false -> 846 ?DBG("merging agent env -> " 847 "no mib-storage ~p merge needed - " 848 "no old options", [NewModule]), 849 NewMibStorage; 850 {value, {options, OldOptions}} -> 851 MergedOptions = 852 merge_agent_options(NewOptions, OldOptions), 853 ?DBG("merging agent env -> mib-storage ~p merged: " 854 "~n Options: ~p | ~p -> ~p", 855 [NewModule, 856 NewOptions, OldOptions, MergedOptions]), 857 [{module, NewModule}, 858 {options, MergedOptions}] 859 end 860 end; 861 _ -> 862 %% Diff module => replace 863 ?DBG("merging agent env -> " 864 "no mib-storage ~p merge needed - " 865 "new module", [NewModule]), 866 NewMibStorage 867 end. 868 869merge_or_replace_agent_env_mib_server(New, Old) -> 870 MibServer = merge_agent_options(New, Old), 871 ?DBG("merging agent env -> mib-server merged: " 872 "~n ~p | ~p -> ~p", [New, Old, MibServer]), 873 MibServer. 874 875merge_or_replace_agent_env_symbolic_store(New, Old) -> 876 SymbolicStore = merge_agent_options(New, Old), 877 ?DBG("merging agent env -> symbolic-store merged: " 878 "~n ~p | ~p -> ~p", [New, Old, SymbolicStore]), 879 SymbolicStore. 880 881merge_or_replace_agent_env_note_store(New, Old) -> 882 NoteStore = merge_agent_options(New, Old), 883 ?DBG("merging agent env -> note-store merged: " 884 "~n ~p | ~p -> ~p", [New, Old, NoteStore]), 885 NoteStore. 886 887merge_or_replace_agent_env_net_if(New, Old) -> 888 NetIf = merge_agent_options(New, Old), 889 ?DBG("merging agent env -> net-if merged: " 890 "~n ~p | ~p -> ~p", [New, Old, NetIf]), 891 NetIf. 892 893merge_agent_options([], Options) -> 894 lists:keysort(1, Options); 895merge_agent_options([{Key, _Value} = Opt|Opts], Options) -> 896 case lists:keysearch(Key, 1, Options) of 897 {value, _} -> 898 NewOptions = lists:keyreplace(Key, 1, Options, Opt), 899 merge_agent_options(Opts, NewOptions); 900 false -> 901 merge_agent_options(Opts, [Opt|Options]) 902 end. 903 904 905stop_agent(Config) when is_list(Config) -> 906 ?IPRINT("stop_agent -> entry with" 907 "~n Config: ~p",[Config]), 908 909 910 %% Stop the sub-agent (the agent supervisor) 911 {SubSup, SubPar} = ?config(snmp_sub, Config), 912 ?IPRINT("stop_agent -> attempt to stop sub agent (~p)" 913 "~n Sub Sup info: " 914 "~n ~p" 915 "~n Sub Par info: " 916 "~n ~p", 917 [SubSup, ?PINFO(SubSup), ?PINFO(SubPar)]), 918 stop_sup(SubSup, SubPar), 919 Config2 = lists:keydelete(snmp_sub, 1, Config), 920 921 922 %% Stop the master-agent (the top agent supervisor) 923 {MasterSup, MasterPar} = ?config(snmp_sup, Config), 924 ?IPRINT("stop_agent -> attempt to stop master agent (~p)" 925 "~n Master Sup: " 926 "~n ~p" 927 "~n Master Par: " 928 "~n ~p" 929 "~n Agent Info: " 930 "~n ~p", 931 [MasterSup, 932 ?PINFO(MasterSup), ?PINFO(MasterPar), 933 agent_info(MasterSup)]), 934 stop_sup(MasterSup, MasterPar), 935 Config3 = lists:keydelete(snmp_sup, 1, Config2), 936 937 938 %% Stop the top supervisor (of the snmp app) 939 AppSup = ?config(snmp_app_sup, Config), 940 ?IPRINT("stop_agent -> attempt to app sup ~p" 941 "~n App Sup: ~p", 942 [AppSup, ?PINFO(AppSup)]), 943 Config4 = lists:keydelete(snmp_app_sup, 1, Config3), 944 945 946 ?IPRINT("stop_agent -> done", []), 947 Config4. 948 949 950start_sup(Env) -> 951 case (catch snmp_app_sup:start_agent(normal, Env)) of 952 {ok, S} -> 953 ?DBG("start_agent -> started, Sup: ~p", [S]), 954 S; 955 956 Else -> 957 ?EPRINT("start_agent -> unknown result: ~n~p", [Else]), 958 %% Get info about the apps we depend on 959 ?FAIL({start_failed, Else, ?IS_MNESIA_RUNNING()}) 960 end. 961 962stop_sup(Pid, _) when (node(Pid) =:= node()) -> 963 case (catch process_info(Pid)) of 964 PI when is_list(PI) -> 965 ?IPRINT("stop_sup -> attempt to stop ~p", [Pid]), 966 Ref = erlang:monitor(process, Pid), 967 exit(Pid, kill), 968 await_stopped(Pid, Ref); 969 {'EXIT', _Reason} -> 970 ?IPRINT("stop_sup -> ~p not running", [Pid]), 971 ok 972 end; 973stop_sup(Pid, _) -> 974 ?IPRINT("stop_sup -> attempt to stop ~p", [Pid]), 975 Ref = erlang:monitor(process, Pid), 976 ?IPRINT("stop_sup -> Ref: ~p", [Ref]), 977 exit(Pid, kill), 978 await_stopped(Pid, Ref). 979 980await_stopped(Pid, Ref) -> 981 receive 982 {'DOWN', Ref, process, Pid, _Reason} -> 983 ?DBG("received down message for ~p", [Pid]), 984 ok 985 after 10000 -> 986 ?EPRINT("await_stopped -> timeout for ~p",[Pid]), 987 erlang:demonitor(Ref), 988 ?FAIL({failed_stop,Pid}) 989 end. 990 991 992%% --- start subagent supervisor --- 993 994start_sub_sup(Node, Dir) -> 995 rpc:call(Node, ?MODULE, start_sub_sup, [Dir]). 996 997start_sub_sup(Dir) -> 998 ?DBG("start_sub -> entry",[]), 999 Opts = [{db_dir, Dir}, 1000 {supervisor, [{verbosity, trace}]}], 1001 {ok, P} = snmpa_supervisor:start_sub_sup(Opts), 1002 unlink(P), 1003 {ok, {P, self()}}. 1004 1005 1006%% --- start and stop subagents --- 1007 1008start_subagent(SaNode, RegTree, Mib) -> 1009 ?DBG("start_subagent -> entry with" 1010 "~n SaNode: ~p" 1011 "~n RegTree: ~p" 1012 "~n Mib: ~p", [SaNode, RegTree, Mib]), 1013 MA = whereis(snmp_master_agent), 1014 ?DBG("start_subagent -> MA: ~p", [MA]), 1015 MibDir = get(mib_dir), 1016 Mib1 = join(MibDir, Mib), 1017 Mod = snmpa_supervisor, 1018 Func = start_sub_agent, 1019 Args = [MA, RegTree, [Mib1]], 1020 case rpc:call(SaNode, Mod, Func, Args) of 1021 {ok, SA} -> 1022 ?DBG("start_subagent -> SA: ~p", [SA]), 1023 {ok, SA}; 1024 Error -> 1025 ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) 1026 end. 1027 1028stop_subagent(SA) -> 1029 ?DBG("stop_subagent -> entry with" 1030 "~n SA: ~p", [SA]), 1031 rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). 1032 1033 1034mibs(StdMibDir,MibDir) -> 1035 [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), 1036 join(MibDir, "OLD-SNMPEA-MIB.bin"), 1037 join(StdMibDir, "SNMP-FRAMEWORK-MIB"), 1038 join(StdMibDir, "SNMP-MPD-MIB"), 1039 join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), 1040 join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), 1041 join(StdMibDir, "SNMP-TARGET-MIB"), 1042 join(StdMibDir, "SNMP-NOTIFICATION-MIB"), 1043 join(MibDir, "Klas1.bin"), 1044 join(MibDir, "Klas2.bin"), 1045 join(MibDir, "Klas3.bin"), 1046 join(MibDir, "Klas4.bin"), 1047 join(MibDir, "SA-MIB.bin"), 1048 join(MibDir, "TestTrap.bin"), 1049 join(MibDir, "Test1.bin"), 1050 join(MibDir, "Test2.bin"), 1051 join(MibDir, "TestTrapv2.bin")]. 1052 1053 1054%% --- various mib load/unload functions --- 1055 1056load_master(Mib) -> 1057 ?DBG("load_master -> entry with" 1058 "~n Mib: ~p", [Mib]), 1059 snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety 1060 ok = snmpa:load_mib(snmp_master_agent, join(get(mib_dir), Mib)). 1061 1062load_master_std(Mib) -> 1063 ?DBG("load_master_std -> entry with" 1064 "~n Mib: ~p", [Mib]), 1065 snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety 1066 ok = snmpa:load_mibs(snmp_master_agent, join(get(std_mib_dir), Mib)). 1067 1068unload_master(Mib) -> 1069 ?DBG("unload_master -> entry with" 1070 "~n Mib: ~p", [Mib]), 1071 ok = snmpa:unload_mib(snmp_master_agent, Mib). 1072 1073loaded_mibs() -> 1074 ?DBG("loaded_mibs -> entry",[]), 1075 Info = snmpa:info(snmp_master_agent), 1076 {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), 1077 [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. 1078 1079unload_mibs(Mibs) -> 1080 ?DBG("unload_mibs -> entry with" 1081 "~n Mibs: ~p", [Mibs]), 1082 ok = snmpa:unload_mibs(snmp_master_agent, Mibs). 1083 1084 1085agent_info(Sup) -> 1086 ?DBG("agent_info -> entry with" 1087 "~n Sup: ~p", [Sup]), 1088 rpc:call(node(Sup), snmpa, info, []). 1089 1090 1091%% --- 1092%% The first two arguments are simple to be able to find where in the 1093%% (test) code this call is made. 1094 1095expect(Mod, Line, What) -> 1096 Fun = fun() -> do_expect(What) end, 1097 expect2(Mod, Line, Fun). 1098 1099expect(Mod, Line, What, ExpVBs) -> 1100 Fun = fun() -> do_expect(What, ExpVBs) end, 1101 expect2(Mod, Line, Fun). 1102 1103expect(Mod, Line, Error, Index, ExpVBS) -> 1104 Fun = fun() -> do_expect(Error, Index, ExpVBS) end, 1105 expect2(Mod, Line, Fun). 1106 1107expect(Mod, Line, Type, Enterp, Generic, Specific, ExpVBs) -> 1108 Fun = fun() -> do_expect(Type, Enterp, Generic, Specific, ExpVBs) end, 1109 expect2(Mod, Line, Fun). 1110 1111expect2(Mod, Line, F) -> 1112 io_format_expect("for ~w:~w", [Mod, Line]), 1113 case F() of 1114 {error, Reason} -> 1115 io_format_expect("failed at ~w:~w => " 1116 "~n ~p", [Mod, Line, Reason]), 1117 throw({error, {expect, Mod, Line, Reason}}); 1118 Else -> 1119 io_format_expect("result for ~w:~w => " 1120 "~n ~p", [Mod, Line, Else]), 1121 Else 1122 end. 1123 1124 1125%% ---------------------------------------------------------------------- 1126 1127-define(BASE_REQ_TIMEOUT, 3500). 1128 1129get_timeout() -> 1130 %% Try to figure out how "fast" a machine is. 1131 %% We assume that the number of schedulers 1132 %% (which depends on the number of core:s) 1133 %% effect the performance of the host... 1134 %% This is obviously not enough. The network 1135 %% also matterns, clock freq or the CPU, ... 1136 %% But its better than what we had before... 1137 case erlang:system_info(schedulers) of 1138 N when is_integer(N) -> 1139 ?BASE_REQ_TIMEOUT + timer:seconds(10 div N); 1140 _ -> 1141 ?BASE_REQ_TIMEOUT 1142 end. 1143 1144receive_pdu(To) -> 1145 receive 1146 {snmp_pdu, PDU} when is_record(PDU, pdu) -> 1147 PDU 1148 after To -> 1149 {error, timeout} 1150 end. 1151 1152receive_trap(To) -> 1153 receive 1154 {snmp_pdu, PDU} when is_record(PDU, trappdu) -> 1155 PDU 1156 after To -> 1157 {error, timeout} 1158 end. 1159 1160 1161io_format_expect(F) -> 1162 io_format_expect(F, []). 1163 1164io_format_expect(F, A) -> 1165 ?IPRINT("EXPECT " ++ F, A). 1166 1167 1168do_expect(Expect) when is_atom(Expect) -> 1169 do_expect({Expect, get_timeout()}); 1170 1171do_expect({any_pdu, To}) 1172 when is_integer(To) orelse (To =:= infinity) -> 1173 io_format_expect("any PDU"), 1174 receive_pdu(To); 1175 1176do_expect({any_trap, To}) -> 1177 io_format_expect("any TRAP within ~w", [To]), 1178 receive_trap(To); 1179 1180do_expect({timeout, To}) -> 1181 io_format_expect("nothing within ~w", [To]), 1182 receive 1183 X -> 1184 {error, {unexpected, X}} 1185 after 1186 To -> 1187 ok 1188 end; 1189 1190do_expect({Err, To}) 1191 when (is_atom(Err) andalso 1192 ((is_integer(To) andalso To > 0) orelse (To =:= infinity))) -> 1193 io_format_expect("error ~w within ~w", [Err, To]), 1194 do_expect({{error, Err}, To}); 1195 1196do_expect({error, Err}) when is_atom(Err) -> 1197 Check = fun(_, R) -> R end, 1198 io_format_expect("error ~w", [Err]), 1199 do_expect2(Check, any, Err, any, any, get_timeout()); 1200do_expect({{error, Err}, To}) -> 1201 Check = fun(_, R) -> R end, 1202 io_format_expect("error ~w within ~w", [Err, To]), 1203 do_expect2(Check, any, Err, any, any, To); 1204 1205%% exp_varbinds() -> [exp_varbind()] 1206%% exp_varbind() -> any | {Oid, any} | {Oid, Value} 1207%% Oid -> [integer()] 1208%% Value -> term() 1209%% ExpVBs -> exp_varbinds() | {VbsCondition, exp_varbinds()} 1210do_expect(ExpVBs) -> 1211 Check = fun(_, R) -> R end, 1212 io_format_expect("'get-response'" 1213 "~n with" 1214 "~n Varbinds: ~p", [ExpVBs]), 1215 do_expect2(Check, 'get-response', noError, 0, ExpVBs, get_timeout()). 1216 1217 1218do_expect(v2trap, ExpVBs) -> 1219 Check = fun(_, R) -> R end, 1220 io_format_expect("'snmpv2-trap' with" 1221 "~n Varbinds: ~p", [ExpVBs]), 1222 do_expect2(Check, 'snmpv2-trap', noError, 0, ExpVBs, get_timeout()); 1223 1224 1225do_expect(report, ExpVBs) -> 1226 Check = fun(_, R) -> R end, 1227 io_format_expect("'report' with" 1228 "~n Varbinds: ~p", [ExpVBs]), 1229 do_expect2(Check, 'report', noError, 0, ExpVBs, get_timeout()); 1230 1231 1232do_expect(inform, ExpVBs) -> 1233 do_expect({inform, true}, ExpVBs); 1234 1235do_expect({inform, false}, ExpVBs) -> 1236 Check = fun(_, R) -> R end, 1237 io_format_expect("'inform-request' (false) with" 1238 "~n Varbinds: ~p", [ExpVBs]), 1239 do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); 1240 1241do_expect({inform, true}, ExpVBs) -> 1242 Check = 1243 fun(PDU, ok) -> 1244 RespPDU = PDU#pdu{type = 'get-response', 1245 error_status = noError, 1246 error_index = 0}, 1247 snmp_test_mgr:rpl(RespPDU), 1248 ok; 1249 (_, Err) -> 1250 Err 1251 end, 1252 io_format_expect("'inform-request' (true) with" 1253 "~n Varbinds: ~p", [ExpVBs]), 1254 do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); 1255 1256do_expect({inform, {error, EStat, EIdx}}, ExpVBs) 1257 when is_atom(EStat) andalso is_integer(EIdx) -> 1258 Check = 1259 fun(PDU, ok) -> 1260 RespPDU = PDU#pdu{type = 'get-response', 1261 error_status = EStat, 1262 error_index = EIdx}, 1263 snmp_test_mgr:rpl(RespPDU), 1264 ok; 1265 (_, Err) -> 1266 Err 1267 end, 1268 io_format_expect("'inform-request' (error) with" 1269 "~n Error Status: ~p" 1270 "~n Error Index: ~p" 1271 "~n Varbinds: ~p", [EStat, EIdx, ExpVBs]), 1272 do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()). 1273 1274 1275do_expect(Err, Idx, ExpVBs) -> 1276 do_expect(Err, Idx, ExpVBs, get_timeout()). 1277 1278do_expect(Err, Idx, ExpVBs, To) 1279 when is_atom(Err) andalso 1280 (is_integer(Idx) orelse is_list(Idx) orelse (Idx == any)) -> 1281 Check = fun(_, R) -> R end, 1282 io_format_expect("'get-response' withing ~w ms with" 1283 "~n Error: ~p" 1284 "~n Index: ~p" 1285 "~n Varbinds: ~p", [To, Err, Idx, ExpVBs]), 1286 do_expect2(Check, 'get-response', Err, Idx, ExpVBs, To). 1287 1288 1289do_expect(Type, Enterp, Generic, Specific, ExpVBs) -> 1290 do_expect(Type, Enterp, Generic, Specific, ExpVBs, get_timeout()). 1291 1292do_expect(trap, Enterp, Generic, Specific, ExpVBs, To) -> 1293 io_format_expect("trap within ~w ms with" 1294 "~n Enterp: ~w" 1295 "~n Generic: ~w" 1296 "~n Specific: ~w" 1297 "~n Varbinds: ~w", 1298 [To, Enterp, Generic, Specific, ExpVBs]), 1299 PureE = purify_oid(Enterp), 1300 case receive_trap(To) of 1301 #trappdu{enterprise = PureE, 1302 generic_trap = Generic, 1303 specific_trap = Specific, 1304 varbinds = VBs} -> 1305 check_vbs(purify_oids(ExpVBs), VBs); 1306 1307 #trappdu{enterprise = Ent2, 1308 generic_trap = G2, 1309 specific_trap = Spec2, 1310 varbinds = VBs} -> 1311 {error, {unexpected_trap, 1312 {PureE, Generic, Specific, ExpVBs}, 1313 {Ent2, G2, Spec2, VBs}}}; 1314 1315 {error, timeout} = Error -> 1316 SysEvs = snmp_test_global_sys_monitor:events(), 1317 io_format_expect("[expecting trap] got timeout when system events:" 1318 "~n ~p", [SysEvs]), 1319 if 1320 (SysEvs =:= []) -> 1321 Error; 1322 true -> 1323 skip({system_events, SysEvs}) 1324 end; 1325 1326 1327 Error -> 1328 Error 1329 end. 1330 1331 1332do_expect2(Check, Type, Err, Idx, ExpVBs, To) 1333 when is_function(Check) andalso 1334 is_atom(Type) andalso 1335 is_atom(Err) andalso 1336 (is_integer(Idx) orelse is_list(Idx) orelse (Idx =:= any)) andalso 1337 (is_list(ExpVBs) orelse (ExpVBs =:= any)) andalso 1338 (is_integer(To) orelse (To =:= infinity)) -> 1339 1340 case receive_pdu(To) of 1341 1342 #pdu{type = Type, 1343 error_status = Err, 1344 error_index = Idx} when ExpVBs =:= any -> 1345 io_format_expect("received expected pdu (1)"), 1346 ok; 1347 1348 #pdu{type = Type, 1349 request_id = ReqId, 1350 error_status = Err2, 1351 error_index = Idx} when ExpVBs =:= any -> 1352 io_format_expect("received expected pdu with " 1353 "unexpected error status (2): " 1354 "~n Error Status: ~p", [Err2]), 1355 {error, {unexpected_error_status, Err, Err2, ReqId}}; 1356 1357 #pdu{error_status = Err} when (Type =:= any) andalso 1358 (Idx =:= any) andalso 1359 (ExpVBs =:= any) -> 1360 io_format_expect("received expected pdu (3)"), 1361 ok; 1362 1363 #pdu{request_id = ReqId, 1364 error_status = Err2} when (Type =:= any) andalso 1365 (Idx =:= any) andalso 1366 (ExpVBs =:= any) -> 1367 io_format_expect("received expected pdu with " 1368 "unexpected error status (4): " 1369 "~n Error Status: ~p", [Err2]), 1370 {error, {unexpected_error_status, Err, Err2, ReqId}}; 1371 1372 #pdu{type = Type, 1373 error_status = Err} when (Idx =:= any) andalso 1374 (ExpVBs =:= any) -> 1375 io_format_expect("received expected pdu (5)", []), 1376 ok; 1377 1378 #pdu{type = Type, 1379 request_id = ReqId, 1380 error_status = Err2} when (Idx =:= any) andalso 1381 (ExpVBs =:= any) -> 1382 io_format_expect("received expected pdu with " 1383 "unexpected error status (6): " 1384 "~n Error Status: ~p", [Err2]), 1385 {error, {unexpected_error_status, Err, Err2, ReqId}}; 1386 1387 #pdu{type = Type, 1388 request_id = ReqId, 1389 error_status = Err, 1390 error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> 1391 case lists:member(EI, Idx) of 1392 true -> 1393 io_format_expect("received expected pdu with " 1394 "expected error index (7)"), 1395 ok; 1396 false -> 1397 io_format_expect("received expected pdu with " 1398 "unexpected error index (8): " 1399 "~n Error Index: ~p", [EI]), 1400 {error, {unexpected_error_index, EI, Idx, ReqId}} 1401 end; 1402 1403 #pdu{type = Type, 1404 request_id = ReqId, 1405 error_status = Err2, 1406 error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> 1407 case lists:member(EI, Idx) of 1408 true -> 1409 io_format_expect("received expected pdu with " 1410 "unexpected error status (9): " 1411 "~n Error Status: ~p", [Err2]), 1412 {error, {unexpected_error_status, Err, Err2, ReqId}}; 1413 false -> 1414 io_format_expect("received expected pdu with " 1415 "unexpected error (10): " 1416 "~n Error Status: ~p" 1417 "~n Error index: ~p", [Err2, EI]), 1418 {error, {unexpected_error, {Err, Idx}, {Err2, EI}, ReqId}} 1419 end; 1420 1421 #pdu{type = Type2, 1422 request_id = ReqId, 1423 error_status = Err2, 1424 error_index = Idx2} when ExpVBs =:= any -> 1425 io_format_expect("received unexpected pdu with (11) " 1426 "~n Type: ~p" 1427 "~n ReqId: ~p" 1428 "~n Error status: ~p" 1429 "~n Error index: ~p", 1430 [Type2, ReqId, Err2, Idx2]), 1431 {error, 1432 {unexpected_pdu, 1433 {Type, Err, Idx}, {Type2, Err2, Idx2}, ReqId}}; 1434 1435 #pdu{type = Type, 1436 error_status = Err, 1437 error_index = Idx, 1438 varbinds = VBs} = PDU -> 1439 io_format_expect("received pdu (12): " 1440 "~n [exp] Type: ~p" 1441 "~n [exp] Error Status: ~p" 1442 "~n [exp] Error Index: ~p" 1443 "~n VBs: ~p" 1444 "~nwhen" 1445 "~n ExpVBs: ~p", 1446 [Type, Err, Idx, VBs, ExpVBs]), 1447 Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); 1448 1449 #pdu{type = Type, 1450 error_status = Err, 1451 varbinds = VBs} = PDU when Idx =:= any -> 1452 io_format_expect("received pdu (13): " 1453 "~n [exp] Type: ~p" 1454 "~n [exp] Error Status: ~p" 1455 "~n VBs: ~p" 1456 "~nwhen" 1457 "~n ExpVBs: ~p", 1458 [Type, Err, VBs, ExpVBs]), 1459 Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); 1460 1461 #pdu{type = Type, 1462 request_id = ReqId, 1463 error_status = Err, 1464 error_index = EI, 1465 varbinds = VBs} = PDU when is_list(Idx) -> 1466 io_format_expect("received pdu (14): " 1467 "~n [exp] Type: ~p" 1468 "~n ReqId: ~p" 1469 "~n [exp] Error Status: ~p" 1470 "~n [exp] Error Index: ~p" 1471 "~n VBs: ~p" 1472 "~nwhen" 1473 "~n ExpVBs: ~p", 1474 [Type, ReqId, Err, EI, VBs, ExpVBs]), 1475 PureVBs = purify_oids(ExpVBs), 1476 case lists:member(EI, Idx) of 1477 true -> 1478 Check(PDU, check_vbs(PureVBs, VBs)); 1479 false -> 1480 {error, {unexpected_error_index, Idx, EI, ReqId}} 1481 end; 1482 1483 #pdu{type = Type2, 1484 request_id = ReqId, 1485 error_status = Err2, 1486 error_index = Idx2, 1487 varbinds = VBs2} -> 1488 io_format_expect("received unexpected pdu with (15) " 1489 "~n Type: ~p" 1490 "~n ReqId: ~p" 1491 "~n Error status: ~p" 1492 "~n Error index: ~p" 1493 "~n Varbinds: ~p", 1494 [Type2, ReqId, Err2, Idx2, VBs2]), 1495 {error, 1496 {unexpected_pdu, 1497 {Type, Err, Idx, purify_oids(ExpVBs)}, 1498 {Type2, Err2, Idx2, VBs2}, 1499 ReqId}}; 1500 1501 1502 {error, timeout} = Error -> 1503 SysEvs = snmp_test_global_sys_monitor:events(), 1504 io_format_expect("got timeout (16) when system events:" 1505 "~n ~p", [SysEvs]), 1506 if 1507 (SysEvs =:= []) -> 1508 Error; 1509 true -> 1510 skip({system_events, SysEvs}) 1511 end; 1512 1513 1514 Error -> 1515 io_format_expect("received error (17): " 1516 "~n Error: ~p", [Error]), 1517 Error 1518 end. 1519 1520 1521 1522check_vbs([], []) -> 1523 ok; 1524check_vbs(Exp, []) -> 1525 {error, {to_few_vbs, Exp}}; 1526check_vbs([], VBs) -> 1527 {error, {to_many_vbs, VBs}}; 1528check_vbs([any|Exp], [_|VBs]) -> 1529 check_vbs(Exp, VBs); 1530check_vbs([{Oid, any}|Exp], [#varbind{oid = Oid}|VBs]) -> 1531 check_vbs(Exp, VBs); 1532check_vbs([{Oid, Val}|Exp], [#varbind{oid = Oid, value = Val}|VBs]) -> 1533 check_vbs(Exp, VBs); 1534check_vbs([{Oid, Val1}|_], [#varbind{oid = Oid, value = Val2}|_]) -> 1535 {error, {unexpected_vb_value, Oid, Val1, Val2}}; 1536check_vbs([{Oid1, _}|_], [#varbind{oid = Oid2}|_]) -> 1537 {error, {unexpected_vb_oid, Oid1, Oid2}}. 1538 1539 1540purify_oids({VbsCondition, VBs}) 1541 when ((VbsCondition =:= true) orelse (VbsCondition =:= false)) andalso 1542 is_list(VBs) -> 1543 {VbsCondition, do_purify_oids(VBs)}; 1544purify_oids(VBs) when is_list(VBs) -> 1545 do_purify_oids(VBs). 1546 1547do_purify_oids([]) -> 1548 []; 1549do_purify_oids([{XOid, Q}|T]) -> 1550 [{purify_oid(XOid), Q} | do_purify_oids(T)]. 1551 1552 1553purify_oid(Oid) -> 1554 io:format("~w:purify_oid -> entry with" 1555 "~n Oid: ~w" 1556 "~n", 1557 [?MODULE, Oid]), 1558 case (catch snmp_test_mgr:purify_oid(Oid)) of 1559 {error, Reason} -> 1560 io:format("~w:purify_oid -> error: " 1561 "~n Reason: ~p" 1562 "~n", 1563 [?MODULE, Reason]), 1564 exit({malformed_oid, Reason}); 1565 {ok, Oid2} when is_list(Oid2) -> 1566 io:format("~w:purify_oid -> ok: " 1567 "~n Oid2: ~p" 1568 "~n", 1569 [?MODULE, Oid2]), 1570 Oid2; 1571 Error -> 1572 io:format("~w:purify_oid -> unexpected return value: " 1573 "~n Error: ~p" 1574 "~n", 1575 [?MODULE, Error]), 1576 exit({unexpected_purify_result, Error}) 1577 1578 end. 1579 1580 1581%% ---------------------------------------------------------------------- 1582 1583get_req(Id, Vars) -> 1584 ?DBG("get_req -> entry with" 1585 "~n Id: ~p" 1586 "~n Vars: ~p",[Id,Vars]), 1587 snmp_test_mgr:g(Vars), 1588 ?DBG("get_req -> await response",[]), 1589 case snmp_test_mgr:get_response(Id, Vars) of 1590 {ok, Val} -> 1591 ?DBG("get_req -> response: ~p",[Val]), 1592 Val; 1593 {error, _, {_ExpFmt, ExpArg}, {_ActFmt, ActArg}} -> 1594 ?DBG("get_req -> error for ~p: " 1595 "~n " ++ _ExpFmt ++ 1596 "~n " ++ _ActFmt, 1597 [Id] ++ ExpArg ++ ActArg), 1598 exit({unexpected_response, ExpArg, ActArg}); 1599 Error -> 1600 ?DBG("get_req -> error: ~n~p",[Error]), 1601 exit({unknown, Error}) 1602 end. 1603 1604 1605get_next_req(Vars) -> 1606 ?DBG("get_next_req -> entry with" 1607 "~n Vars: ~p", [Vars]), 1608 snmp_test_mgr:gn(Vars), 1609 ?DBG("get_next_req -> await response",[]), 1610 Response = snmp_test_mgr:receive_response(), 1611 ?DBG("get_next_req -> response: ~p",[Response]), 1612 Response. 1613 1614 1615%% --- start and stop nodes --- 1616 1617start_node(Name) -> 1618 ?IPRINT("start_node -> entry with" 1619 "~n Name: ~p" 1620 "~n when" 1621 "~n hostname of this node: ~p", 1622 [Name, list_to_atom(?HOSTNAME(node()))]), 1623 1624 Pa = filename:dirname(code:which(?MODULE)), 1625 ?DBG("start_node -> Pa: ~p", [Pa]), 1626 1627 A = " -pa " ++ Pa ++ 1628 " -s " ++ atom_to_list(snmp_test_sys_monitor) ++ " start" ++ 1629 " -s global sync", 1630 case ?START_NODE(Name, A) of 1631 {ok, Node} -> 1632 ?DBG("start_node -> Node: ~p", [Node]), 1633 global:sync(), 1634 {ok, Node}; 1635 {error, Reason} -> 1636 ?WPRINT("start_node -> failed starting node ~p:" 1637 "~n Reason: ~p", [Name, Reason]), 1638 ?line ?SKIP({failed_start_node, Reason}); 1639 Else -> 1640 ?EPRINT("start_node -> failed starting node ~p:" 1641 "~n ~p", [Name, Else]), 1642 ?line ?FAIL(Else) 1643 end. 1644 1645 1646stop_node(Node) -> 1647 ?IPRINT("stop_node -> Node: ~p", [Node]), 1648 ?STOP_NODE(Node). 1649 1650 1651%%%----------------------------------------------------------------- 1652%%% Configuration 1653%%%----------------------------------------------------------------- 1654 1655config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> 1656 config(Vsns, MgrDir, AgentConfDir, MIp, AIp, inet). 1657 1658config(Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily) -> 1659 ?IPRINT("config -> entry with" 1660 "~n Vsns: ~p" 1661 "~n MgrDir: ~p" 1662 "~n AgentConfDir: ~p" 1663 "~n MIp: ~p" 1664 "~n AIp: ~p" 1665 "~n IpFamily: ~p", 1666 [Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily]), 1667 ?line {Domain, ManagerAddr} = 1668 case IpFamily of 1669 inet6 -> 1670 TransportDomain6 = transportDomainUdpIpv6, 1671 AgentAddr6 = {AIp, 4000}, 1672 ManagerAddr6 = {MIp, ?TRAP_UDP}, 1673 ?line ok = 1674 snmp_config:write_agent_snmp_files( 1675 AgentConfDir, Vsns, 1676 TransportDomain6, ManagerAddr6, AgentAddr6, "test"), 1677 {TransportDomain6, ManagerAddr6}; 1678 inet -> 1679 TransportDomain4 = transportDomainUdpIpv4, 1680 AIp2 = maybe_fix_addr(AIp), 1681 ManagerAddr4 = {MIp, ?TRAP_UDP}, 1682 %% AgentPreTransport = 1683 %% [#{addr => {AIp2, 4000}, kind => req_responder}, 1684 %% #{addr => {AIp2, 4001}, kind => trap_sender}], 1685 AgentPreTransport = [#{addr => {AIp2, 4000}}], 1686 ?line ok = 1687 snmp_config:write_agent_snmp_files( 1688 AgentConfDir, Vsns, 1689 TransportDomain4, ManagerAddr4, AgentPreTransport, 1690 "test"), 1691 {TransportDomain4, ManagerAddr4}; 1692 _ -> 1693 ?line ok = 1694 snmp_config:write_agent_snmp_files( 1695 AgentConfDir, Vsns, MIp, ?TRAP_UDP, AIp, 4000, "test"), 1696 {snmpUDPDomain, {MIp, ?TRAP_UDP}} 1697 end, 1698 1699 ?line case update_usm(Vsns, AgentConfDir) of 1700 true -> 1701 ?line copy_file(join(AgentConfDir, "usm.conf"), 1702 join(MgrDir, "usm.conf")), 1703 ?line update_usm_mgr(Vsns, MgrDir); 1704 false -> 1705 ?line ok 1706 end, 1707 ?line update_community(Vsns, AgentConfDir), 1708 ?line update_vacm(Vsns, AgentConfDir), 1709 ?line write_target_addr_conf(AgentConfDir, Domain, ManagerAddr, Vsns), 1710 ?line write_target_params_conf(AgentConfDir, Vsns), 1711 ?line write_notify_conf(AgentConfDir), 1712 ok. 1713 1714maybe_fix_addr(Addr) when is_list(Addr) -> 1715 list_to_tuple(Addr); 1716maybe_fix_addr(Addr) when is_tuple(Addr) -> 1717 Addr. 1718 1719 1720delete_files(Config) -> 1721 AgentDir = ?config(agent_dir, Config), 1722 delete_files(AgentDir, [db, conf]). 1723 1724delete_files(_AgentFiles, []) -> 1725 ok; 1726delete_files(AgentDir, [DirName|DirNames]) -> 1727 Dir = join(AgentDir, DirName), 1728 {ok, Files} = file:list_dir(Dir), 1729 lists:foreach(fun(FName) -> file:delete(join(Dir, FName)) end, 1730 Files), 1731 delete_files(AgentDir, DirNames). 1732 1733update_usm(Vsns, Dir) -> 1734 case lists:member(v3, Vsns) of 1735 true -> 1736 Conf = [{"agentEngine", "all-rights", "all-rights", zeroDotZero, 1737 usmNoAuthProtocol, "", "", 1738 usmNoPrivProtocol, "", "", "", "", ""}, 1739 1740 {"agentEngine", "no-rights", "no-rights", zeroDotZero, 1741 usmNoAuthProtocol, "", "", 1742 usmNoPrivProtocol, "", "", "", "", ""}, 1743 1744 {"agentEngine", "authMD5", "authMD5", zeroDotZero, 1745 usmHMACMD5AuthProtocol, "", "", 1746 usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, 1747 1748 {"agentEngine", "authSHA", "authSHA", zeroDotZero, 1749 usmHMACSHAAuthProtocol, "", "", 1750 usmNoPrivProtocol, "", "", "", 1751 "passwd_shaxxxxxxxxxx", ""}, 1752 1753 {"agentEngine", "privDES", "privDES", zeroDotZero, 1754 usmHMACSHAAuthProtocol, "", "", 1755 usmDESPrivProtocol, "", "", "", 1756 "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, 1757 1758 {"mgrEngine", "all-rights", "all-rights", zeroDotZero, 1759 usmNoAuthProtocol, "", "", 1760 usmNoPrivProtocol, "", "", "", "", ""}, 1761 1762 {"mgrEngine", "no-rights", "no-rights", zeroDotZero, 1763 usmNoAuthProtocol, "", "", 1764 usmNoPrivProtocol, "", "", "", "", ""}, 1765 1766 {"mgrEngine", "authMD5", "authMD5", zeroDotZero, 1767 usmHMACMD5AuthProtocol, "", "", 1768 usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, 1769 1770 {"mgrEngine", "authSHA", "authSHA", zeroDotZero, 1771 usmHMACSHAAuthProtocol, "", "", 1772 usmNoPrivProtocol, "", "", "", 1773 "passwd_shaxxxxxxxxxx", ""}, 1774 1775 {"mgrEngine", "privDES", "privDES", zeroDotZero, 1776 usmHMACSHAAuthProtocol, "", "", 1777 usmDESPrivProtocol, "", "", "", 1778 "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], 1779 ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), 1780 true; 1781 false -> 1782 false 1783 end. 1784 1785update_usm_mgr(Vsns, Dir) -> 1786 case lists:member(v3, Vsns) of 1787 true -> 1788 Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, 1789 usmHMACSHAAuthProtocol, "", "", 1790 usmDESPrivProtocol, "", "", "", 1791 "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, 1792 1793 {"mgrEngine", "newUser", "newUser", zeroDotZero, 1794 usmHMACSHAAuthProtocol, "", "", 1795 usmDESPrivProtocol, "", "", "", 1796 "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], 1797 1798 ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), 1799 true; 1800 false -> 1801 false 1802 end. 1803 1804rewrite_usm_mgr(Dir, ShaKey, DesKey) -> 1805 ?line ok = file:rename(join(Dir,"usm.conf"), 1806 join(Dir,"usm.old")), 1807 Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, 1808 usmHMACSHAAuthProtocol, "", "", 1809 usmDESPrivProtocol, "", "", "", ShaKey, DesKey}, 1810 {"mgrEngine", "newUser", "newUser", zeroDotZero, 1811 usmHMACSHAAuthProtocol, "", "", 1812 usmDESPrivProtocol, "", "", "", ShaKey, DesKey}], 1813 ?line ok = snmp_config:write_agent_usm_config(Dir, "", Conf). 1814 1815reset_usm_mgr(Dir) -> 1816 ?line ok = file:rename(join(Dir,"usm.old"), 1817 join(Dir,"usm.conf")). 1818 1819 1820update_community([v3], _Dir) -> 1821 ok; 1822update_community(_, Dir) -> 1823 Conf = [{"no-rights", "no-rights", "no-rights", "", ""}], 1824 ?line ok = snmp_config:update_agent_community_config(Dir, Conf). 1825 1826 1827-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). 1828update_vacm(_Vsn, Dir) -> 1829 Conf = [{vacmSecurityToGroup, usm, "authMD5", "initial"}, 1830 {vacmSecurityToGroup, usm, "authSHA", "initial"}, 1831 {vacmSecurityToGroup, usm, "privDES", "initial"}, 1832 {vacmSecurityToGroup, usm, "newUser", "initial"}, 1833 {vacmViewTreeFamily, "internet", ?tDescr_instance, 1834 excluded, null}], 1835 ?line ok = snmp_config:update_agent_vacm_config(Dir, Conf). 1836 1837 1838write_community_conf(Dir, Conf) -> 1839 ?line ok = snmp_config:write_agent_community_config(Dir, "", Conf). 1840 1841write_target_addr_conf(Dir, Conf) -> 1842 ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", Conf). 1843 1844write_target_addr_conf(Dir, Ip_or_Domain, Port_or_Addr, Vsns) -> 1845 ?line ok = 1846 snmp_config:write_agent_snmp_target_addr_conf( 1847 Dir, Ip_or_Domain, Port_or_Addr, Vsns). 1848 1849rewrite_target_addr_conf(Dir, NewPort) -> 1850 ?DBG("rewrite_target_addr_conf -> entry with" 1851 "~n NewPort: ~p", [NewPort]), 1852 TAFile = join(Dir, "target_addr.conf"), 1853 case file:read_file_info(TAFile) of 1854 {ok, _} -> 1855 ok; 1856 {error, _R} -> 1857 ?WPRINT("failure reading file info of " 1858 "target address config file: ~p", [_R]), 1859 ok 1860 end, 1861 1862 ?line [TrapAddr|Addrs] = 1863 snmp_conf:read(TAFile, fun rewrite_target_addr_conf_check/1), 1864 1865 ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), 1866 1867 NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], 1868 1869 ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), 1870 1871 ?line ok = file:rename(join(Dir,"target_addr.conf"), 1872 join(Dir,"target_addr.old")), 1873 1874 ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs). 1875 1876rewrite_target_addr_conf_check(O) -> 1877 {ok,O}. 1878 1879rewrite_target_addr_conf2(NewPort, 1880 {Name, Ip, _Port, Timeout, Retry, 1881 "std_trap", EngineId}) -> 1882 ?IPRINT("rewrite_target_addr_conf2 -> entry with std_trap",[]), 1883 {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; 1884rewrite_target_addr_conf2(_NewPort,O) -> 1885 ?IPRINT("rewrite_target_addr_conf2 -> entry with " 1886 "~n O: ~p",[O]), 1887 O. 1888 1889reset_target_addr_conf(Dir) -> 1890 ?line ok = file:rename(join(Dir, "target_addr.old"), 1891 join(Dir, "target_addr.conf")). 1892 1893write_target_params_conf(Dir, Vsns) -> 1894 F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; 1895 (v2) -> {"target_v2", v2c, v2c, "all-rights", noAuthNoPriv}; 1896 (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} 1897 end, 1898 Conf = [F(Vsn) || Vsn <- Vsns], 1899 ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). 1900 1901rewrite_target_params_conf(Dir, SecName, SecLevel) 1902 when is_list(SecName) andalso is_atom(SecLevel) -> 1903 ?line ok = file:rename(join(Dir,"target_params.conf"), 1904 join(Dir,"target_params.old")), 1905 Conf = [{"target_v3", v3, usm, SecName, SecLevel}], 1906 ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). 1907 1908reset_target_params_conf(Dir) -> 1909 ?line ok = file:rename(join(Dir,"target_params.old"), 1910 join(Dir,"target_params.conf")). 1911 1912write_notify_conf(Dir) -> 1913 Conf = [{"standard trap", "std_trap", trap}, 1914 {"standard inform", "std_inform", inform}], 1915 ?line ok = snmp_config:write_agent_notify_config(Dir, "", Conf). 1916 1917write_view_conf(Dir) -> 1918 Conf = [{2, [1,3,6], included, null}, 1919 {2, ?tDescr_instance, excluded, null}], 1920 ?line ok = snmp_config:write_agent_view_config(Dir, "", Conf). 1921 1922 1923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1924 1925copy_file(From, To) -> 1926 {ok, Bin} = file:read_file(From), 1927 ok = file:write_file(To, Bin). 1928 1929 1930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1931 1932display_memory_usage() -> 1933 Info = snmpa:info(snmp_master_agent), 1934 TreeSize = key1search(tree_size_bytes, Info), 1935 ProcMem = key1search(process_memory, Info), 1936 MibDbSize = key1search([db_memory,mib], Info), 1937 NodeDbSize = key1search([db_memory,node], Info), 1938 TreeDbSize = key1search([db_memory,tree], Info), 1939 ?IPRINT("Memory usage: " 1940 "~n Tree size: ~p" 1941 "~n Process memory size: ~p" 1942 "~n Mib db size: ~p" 1943 "~n Node db size: ~p" 1944 "~n Tree db size: ~p", 1945 [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). 1946 1947key1search([], Res) -> 1948 Res; 1949key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> 1950 case lists:keysearch(Key, 1, List) of 1951 {value, {Key, Val}} -> 1952 key1search(Keys, Val); 1953 false -> 1954 undefined 1955 end; 1956key1search(Key, List) when is_atom(Key) -> 1957 case lists:keysearch(Key, 1, List) of 1958 {value, {Key, Val}} -> 1959 Val; 1960 false -> 1961 undefined 1962 end. 1963 1964 1965regs() -> 1966 lists:sort(registered()). 1967 1968 1969rpc(Node, F, A) -> 1970 rpc:call(Node, snmpa, F, A). 1971 1972 1973join(Dir, File) -> 1974 filename:join(Dir, File). 1975 1976 1977skip(R) -> 1978 exit({skip, R}). 1979 1980