diff options
author | Micael Karlberg <[email protected]> | 2013-10-09 11:28:03 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2013-10-09 11:28:03 +0200 |
commit | f9f49c3ae40eef669ed165efdc4b03ecb551a8a0 (patch) | |
tree | 3085b3e94bb51c8d822c277a6c9786960b4d9f55 | |
parent | e0ecc86e35475b434efa6cccba44074ca1040b7a (diff) | |
parent | bf552c9138427070b1e17c6fc92f8972d8aef112 (diff) | |
download | otp-f9f49c3ae40eef669ed165efdc4b03ecb551a8a0.tar.gz otp-f9f49c3ae40eef669ed165efdc4b03ecb551a8a0.tar.bz2 otp-f9f49c3ae40eef669ed165efdc4b03ecb551a8a0.zip |
Merge branch 'bmk/snmp/create_db_dir/OTP-11352' into bmk/snmp/snmp425_integration
-rw-r--r-- | lib/snmp/doc/src/notes.xml | 71 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmp_app.xml | 7 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmp_config.xml | 9 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_local_db.erl | 8 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_supervisor.erl | 2 | ||||
-rw-r--r-- | lib/snmp/src/app/snmp.appup.src | 42 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_config.erl | 31 | ||||
-rw-r--r-- | lib/snmp/src/misc/snmp_config.erl | 187 | ||||
-rw-r--r-- | lib/snmp/test/snmp_agent_test.erl | 72 | ||||
-rw-r--r-- | lib/snmp/test/snmp_manager_config_test.erl | 43 | ||||
-rw-r--r-- | lib/snmp/vsn.mk | 2 |
11 files changed, 340 insertions, 134 deletions
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 7514c52dda..2b0daf897b 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,6 +34,77 @@ <section> + <title>SNMP Development Toolkit 4.25</title> + <p>Version 4.25 supports code replacement in runtime from/to + version 4.24.2, 4.24.1, 4.24, 4.23.1 and 4.23. </p> + + <section> + <title>Improvements and new features</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>Enable SNMP to create missing database directories. </p> + <p>Add + <seealso marker="snmp_app#db_init_error"> + {db_init_error, create_db_and_dir}</seealso> option to SNMP + <seealso marker="snmp_app#manager_opts_and_types">manager</seealso> + and + <seealso marker="snmp_app#agent_opts_and_types">agent</seealso>. + This allows them to create any missing parent directories for + <c>db_dir</c>, rather than treating any missing directories + as a fatal error. + The default for <c>db_init_error</c>, which is <c>terminate</c>, + is unchanged. </p> + <p>Steve Vinoski</p> + <p>Own Id: OTP-11352</p> + </item> + + </list> + + </section> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <p>-</p> + +<!-- + <list type="bulleted"> + <item> + <p>[agent] + see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and + <seealso marker="snmpa#unload_mibs">unload_mibs</seealso>. </p> + <p>Own Id: OTP-11216</p> + </item> + + </list> +--> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + +<!-- + <list type="bulleted"> + <item> + <p>[manager] The old Addr-and-Port based API functions, previously + long deprecated and marked for deletion in R16B, has now been + removed. </p> + <p>Own Id: OTP-10027</p> + </item> + + </list> +--> + </section> + + </section> <!-- 4.25 --> + + + <section> <title>SNMP Development Toolkit 4.24.2</title> <p>Version 4.24.2 supports code replacement in runtime from/to version 4.24.1, 4.24, 4.23.1 and 4.23. </p> diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index e5a05342c1..9ede75b943 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -763,12 +763,15 @@ </item> <marker id="db_init_error"></marker> - <tag><c>db_init_error() = terminate | create</c></tag> + <tag><c>db_init_error() = terminate | create | create_db_and_dir</c></tag> <item> <p>Defines what to do if the agent or manager is unable to open an existing database file. <c>terminate</c> means that the agent/manager will terminate and <c>create</c> means that the - agent/manager will remove the faulty file(s) and create new ones.</p> + agent/manager will remove the faulty file(s) and create new ones, + and <c>create_db_and_dir</c> means that the agent/manager will + create the database file along with any missing parent directories + for the database file.</p> <p>Default is <c>terminate</c>.</p> </item> diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 61ee7f00ee..30b46e6aa8 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -792,12 +792,15 @@ in so far as it will be converted to the new format if found. </item> <marker id="db_init_error"></marker> - <tag><c>db_init_error() = terminate | create</c></tag> + <tag><c>db_init_error() = terminate | create | create_db_and_dir</c></tag> <item> <p>Defines what to do if the agent is unable to open an existing database file. <c>terminate</c> means that the - agent/manager will terminate and <c>create</c> means that the - agent/manager will remove the faulty file(s) and create new ones.</p> + agent/manager will terminate, <c>create</c> means that the + agent/manager will remove the faulty file(s) and create new ones, + and <c>create_db_and_dir</c> means that the agent/manager will + create the database file along with any missing parent directories + for the database file.</p> <p>Default is <c>terminate</c>.</p> </item> diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index 5198c6ec4e..f991244287 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. 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 @@ -191,6 +191,12 @@ dets_open(DbDir, DbInitError, Opts) -> end end; _ -> + case DbInitError of + create_db_and_dir -> + ok = filelib:ensure_dir(Filename); + _ -> + ok + end, case do_dets_open(Name, Filename, Opts) of {ok, Dets} -> ?vdebug("dets open done",[]), diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl index aebcdbaa84..77ed54bee4 100644 --- a/lib/snmp/src/agent/snmpa_supervisor.erl +++ b/lib/snmp/src/agent/snmpa_supervisor.erl @@ -356,7 +356,7 @@ init([AgentType, Opts]) -> SymStoreSpec = worker_spec(snmpa_symbolic_store, SymStoreArgs, Restart, 2000), - LdbArgs = [Prio, DbDir, LdbOpts], + LdbArgs = [Prio, DbDir, DbInitError, LdbOpts], LocalDbSpec = worker_spec(snmpa_local_db, LdbArgs, Restart, 5000), diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 6edcf7e833..e1bf7692b3 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -29,24 +29,9 @@ %% {add_module, snmpm_net_if_mt} [ - {"4.24.1", - [ - {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []} - ] - }, - {"4.24", - [ - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, - [snmp_conf]}, - {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []} - ] - }, + {"4.24.2", [{restart_application, snmp}]}, + {"4.24.1", [{restart_application, snmp}]}, + {"4.24", [{restart_application, snmp}]}, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ], @@ -57,24 +42,9 @@ %% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} [ - {"4.24.1", - [ - {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []} - ] - }, - {"4.24", - [ - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, - [snmp_conf]}, - {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_agent]}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []} - ] - }, + {"4.24.2", [{restart_application, snmp}]}, + {"4.24.1", [{restart_application, snmp}]}, + {"4.24", [{restart_application, snmp}]}, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ] diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 736debe544..2101ad46e1 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1215,6 +1215,12 @@ dets_open(Dir, DbInitError, Repair, AutoSave) -> end end; _ -> + case DbInitError of + create_db_and_dir -> + ok = filelib:ensure_dir(Filename); + _ -> + ok + end, case do_dets_open(Name, Filename, Repair, AutoSave) of {ok, _Dets} -> ok; @@ -1316,7 +1322,14 @@ verify_option({server, ServerOpts}) -> verify_server_opts(ServerOpts); verify_option({note_store, NoteStoreOpts}) -> verify_note_store_opts(NoteStoreOpts); -verify_option({config, ConfOpts}) -> +verify_option({config, ConfOpts0}) -> + %% Make sure any db_dir option is first in the options list to make it + %% easier to check if the db_init_error option specifies that a missing + %% db_dir should be created. + ConfOpts = case lists:keytake(db_dir, 1, ConfOpts0) of + false -> ConfOpts0; + {value, Result, OtherOpts} -> [Result|OtherOpts] + end, verify_config_opts(ConfOpts); verify_option({versions, Vsns}) -> verify_versions(Vsns); @@ -1365,7 +1378,12 @@ verify_config_opts([{dir, Dir}|Opts]) -> verify_conf_dir(Dir), verify_config_opts(Opts); verify_config_opts([{db_dir, Dir}|Opts]) -> - verify_conf_db_dir(Dir), + case lists:keyfind(db_init_error, 1, Opts) of + {db_init_error, create_db_and_dir} -> + verify_conf_db_dir(Dir, false); + _ -> + verify_conf_db_dir(Dir, true) + end, verify_config_opts(Opts); verify_config_opts([{db_init_error, DbInitErr}|Opts]) -> verify_conf_db_init_error(DbInitErr), @@ -1443,7 +1461,7 @@ verify_conf_dir(Dir) -> error({invalid_conf_dir, Dir}) end. -verify_conf_db_dir(Dir) -> +verify_conf_db_dir(Dir, true) -> case (catch verify_dir(Dir)) of ok -> ok; @@ -1451,13 +1469,16 @@ verify_conf_db_dir(Dir) -> error({invalid_conf_db_dir, Dir, Reason}); _ -> error({invalid_conf_db_dir, Dir}) - end. - + end; +verify_conf_db_dir(_Dir, false) -> + ok. verify_conf_db_init_error(terminate) -> ok; verify_conf_db_init_error(create) -> ok; +verify_conf_db_init_error(create_db_and_dir) -> + ok; verify_conf_db_init_error(InvalidDbInitError) -> error({invalid_conf_db_init_error, InvalidDbInitError}). diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index 945b8719fc..a222f842e5 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -233,16 +233,18 @@ config_agent_sys() -> fun verify_verbosity/1), DbDir = ask("5. Database directory (absolute path)?", DefDir, fun verify_dir/1), - MibStorageType = ask("6. Mib storage type (ets/dets/mnesia)?", "ets", + DbInitError = ask("6. How to handle DB init error?", + "terminate", fun verify_db_init_error/1), + MibStorageType = ask("7. Mib storage type (ets/dets/mnesia)?", "ets", fun verify_mib_storage_type/1), MibStorage = case MibStorageType of ets -> [{module, snmpa_mib_storage_ets}]; dets -> - DetsDir = ask("6b. Mib storage directory (absolute path)?", + DetsDir = ask("7b. Mib storage directory (absolute path)?", DbDir, fun verify_dir/1), - DetsAction = ask("6c. Mib storage [dets] database start " + DetsAction = ask("7c. Mib storage [dets] database start " "action " "(default/clear/keep)?", "default", fun verify_mib_storage_action/1), @@ -257,7 +259,7 @@ config_agent_sys() -> end; mnesia -> Nodes = [], - MnesiaAction = ask("6b. Mib storage [mnesia] database start " + MnesiaAction = ask("7b. Mib storage [mnesia] database start " "action " "(default/clear/keep)?", "default", fun verify_mib_storage_action/1), @@ -275,80 +277,80 @@ config_agent_sys() -> %% Here we should ask about mib-server data module, %% but as we only have one at the moment... - TargetCacheVerb = ask("7. Target cache verbosity " + TargetCacheVerb = ask("8. Target cache verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - SymStoreVerb = ask("8. Symbolic store verbosity " + SymStoreVerb = ask("9. Symbolic store verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - LocalDbVerb = ask("9. Local DB verbosity " + LocalDbVerb = ask("10. Local DB verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - LocalDbRepair = ask("10. Local DB repair (true/false/force)?", "true", + LocalDbRepair = ask("11. Local DB repair (true/false/force)?", "true", fun verify_dets_repair/1), - LocalDbAutoSave = ask("11. Local DB auto save (infinity/milli seconds)?", + LocalDbAutoSave = ask("12. Local DB auto save (infinity/milli seconds)?", "5000", fun verify_dets_auto_save/1), - ErrorMod = ask("12. Error report module?", "snmpa_error_logger", fun verify_module/1), - Type = ask("13. Agent type (master/sub)?", "master", + ErrorMod = ask("13. Error report module?", "snmpa_error_logger", fun verify_module/1), + Type = ask("14. Agent type (master/sub)?", "master", fun verify_agent_type/1), AgentConfig = case Type of master -> - MasterAgentVerb = ask("14. Master-agent verbosity " + MasterAgentVerb = ask("15. Master-agent verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - ForceLoad = ask("15. Shall the agent re-read the " + ForceLoad = ask("16. Shall the agent re-read the " "configuration files during startup ~n" " (and ignore the configuration " "database) (true/false)?", "true", fun verify_bool/1), - MultiThreaded = ask("16. Multi threaded agent (true/false)?", + MultiThreaded = ask("17. Multi threaded agent (true/false)?", "false", fun verify_bool/1), - MeOverride = ask("17. Check for duplicate mib entries when " + MeOverride = ask("18. Check for duplicate mib entries when " "installing a mib (true/false)?", "false", fun verify_bool/1), - TrapOverride = ask("18. Check for duplicate trap names when " + TrapOverride = ask("19. Check for duplicate trap names when " "installing a mib (true/false)?", "false", fun verify_bool/1), - MibServerVerb = ask("19. Mib server verbosity " + MibServerVerb = ask("20. Mib server verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - MibServerCache = ask("20. Mib server cache " + MibServerCache = ask("21. Mib server cache " "(true/false)?", "true", fun verify_bool/1), - NoteStoreVerb = ask("21. Note store verbosity " + NoteStoreVerb = ask("22. Note store verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - NoteStoreTimeout = ask("22. Note store GC timeout?", "30000", + NoteStoreTimeout = ask("23. Note store GC timeout?", "30000", fun verify_timeout/1), ATL = - case ask("23. Shall the agent use an audit trail log " + case ask("24. Shall the agent use an audit trail log " "(y/n)?", "n", fun verify_yes_or_no/1) of yes -> - ATLType = ask("23b. Audit trail log type " + ATLType = ask("24b. Audit trail log type " "(write/read_write)?", "read_write", fun verify_atl_type/1), - ATLDir = ask("23c. Where to store the " + ATLDir = ask("24c. Where to store the " "audit trail log?", DefDir, fun verify_dir/1), - ATLMaxFiles = ask("23d. Max number of files?", + ATLMaxFiles = ask("24d. Max number of files?", "10", fun verify_pos_integer/1), - ATLMaxBytes = ask("23e. Max size (in bytes) " + ATLMaxBytes = ask("24e. Max size (in bytes) " "of each file?", "10240", fun verify_pos_integer/1), ATLSize = {ATLMaxBytes, ATLMaxFiles}, - ATLRepair = ask("23f. Audit trail log repair " + ATLRepair = ask("24f. Audit trail log repair " "(true/false/truncate/snmp_repair)?", "true", fun verify_atl_repair/1), - ATLSeqNo = ask("23g. Audit trail log " + ATLSeqNo = ask("24g. Audit trail log " "sequence-numbering (true/false)?", "false", fun verify_atl_seqno/1), @@ -360,33 +362,33 @@ config_agent_sys() -> no -> [] end, - NetIfVerb = ask("24. Network interface verbosity " + NetIfVerb = ask("25. Network interface verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - NetIfMod = ask("25. Which network interface module shall be used?", + NetIfMod = ask("26. Which network interface module shall be used?", "snmpa_net_if", fun verify_module/1), NetIfOpts = case NetIfMod of snmpa_net_if -> NetIfBindTo = - ask("25a. Bind the agent IP address " + ask("26a. Bind the agent IP address " "(true/false)?", "false", fun verify_bool/1), NetIfNoReuse = - ask("25b. Shall the agents " + ask("26b. Shall the agents " "IP address " "and port be not reusable " "(true/false)?", "false", fun verify_bool/1), NetIfReqLimit = - ask("25c. Agent request limit " + ask("26c. Agent request limit " "(used for flow control) " "(infinity/pos integer)?", "infinity", fun verify_netif_req_limit/1), NetIfRecbuf = - case ask("25d. Receive buffer size of the " + case ask("26d. Receive buffer size of the " "agent (in bytes) " "(default/pos integer)?", "default", @@ -397,7 +399,7 @@ config_agent_sys() -> [{recbuf, RecBufSz}] end, NetIfSndbuf = - case ask("25e. Send buffer size of the agent " + case ask("26e. Send buffer size of the agent " "(in bytes) (default/pos integer)?", "default", fun verify_netif_sndbuf/1) of @@ -407,7 +409,7 @@ config_agent_sys() -> [{sndbuf, SndBufSz}] end, NetIfFilter = - case ask("25f. Do you wish to specify a " + case ask("26f. Do you wish to specify a " "network interface filter module " "(or use default)", "default", fun verify_module/1) of @@ -426,18 +428,18 @@ config_agent_sys() -> NetIf = [{module, NetIfMod}, {verbosity, NetIfVerb}, {options, NetIfOpts}], - TermDiscoEnable = ask("26a. Allow terminating discovery " + TermDiscoEnable = ask("27. Allow terminating discovery " "(true/false)?", "true", fun verify_bool/1), TermDiscoConf = case TermDiscoEnable of true -> TermDiscoStage2 = - ask("26b. Second stage behaviour " + ask("27a. Second stage behaviour " "(discovery/plain)?", "discovery", fun verify_term_disco_behaviour/1), TermDiscoTrigger = - ask("26c. Trigger username " + ask("27b. Trigger username " "(default/a string)?", "default", fun verify_term_disco_trigger_username/1), [{enable, TermDiscoEnable}, @@ -448,7 +450,7 @@ config_agent_sys() -> {stage2, discovery}, {trigger_username, ""}] end, - OrigDiscoEnable = ask("27a. Allow originating discovery " + OrigDiscoEnable = ask("28. Allow originating discovery " "(true/false)?", "true", fun verify_bool/1), OrigDiscoConf = @@ -471,7 +473,7 @@ config_agent_sys() -> {verbosity, NoteStoreVerb}]}, {net_if, NetIf}] ++ ATL; sub -> - SubAgentVerb = ask("14. Sub-agent verbosity " + SubAgentVerb = ask("15. Sub-agent verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), @@ -480,11 +482,12 @@ config_agent_sys() -> {config, [{dir, ConfigDir}]}] end, SysConfig = - [{priority, Prio}, - {versions, Vsns}, - {db_dir, DbDir}, - {mib_storage, MibStorage}, - {target_cache, [{verbosity, TargetCacheVerb}]}, + [{priority, Prio}, + {versions, Vsns}, + {db_dir, DbDir}, + {db_init_error, DbInitError}, + {mib_storage, MibStorage}, + {target_cache, [{verbosity, TargetCacheVerb}]}, {symbolic_store, [{verbosity, SymStoreVerb}]}, {local_db, [{repair, LocalDbRepair}, {auto_save, LocalDbAutoSave}, @@ -630,19 +633,21 @@ config_manager_sys() -> fun verify_verbosity/1), ConfigDbDir = ask("5. Database directory (absolute path)?", DefDir, fun verify_dir/1), - ConfigDbRepair = ask("6. Database repair " + ConfigDbInitError = ask("6. How to handle DB init error?", + "terminate", fun verify_db_init_error/1), + ConfigDbRepair = ask("7. Database repair " "(true/false/force)?", "true", fun verify_dets_repair/1), - ConfigDbAutoSave = ask("7. Database auto save " + ConfigDbAutoSave = ask("8. Database auto save " "(infinity/milli seconds)?", "5000", fun verify_dets_auto_save/1), IRB = - case ask("8. Inform request behaviour (auto/user)?", + case ask("9. Inform request behaviour (auto/user)?", "auto", fun verify_irb/1) of auto -> auto; user -> - case ask("8b. Use default GC timeout" + case ask("9b. Use default GC timeout" "(default/seconds)?", "default", fun verify_irb_user/1) of default -> @@ -651,31 +656,31 @@ config_manager_sys() -> {user, IrbGcTo} end end, - ServerVerb = ask("9. Server verbosity " + ServerVerb = ask("10. Server verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - ServerTimeout = ask("10. Server GC timeout?", "30000", + ServerTimeout = ask("11. Server GC timeout?", "30000", fun verify_timeout/1), - NoteStoreVerb = ask("11. Note store verbosity " + NoteStoreVerb = ask("12. Note store verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - NoteStoreTimeout = ask("12. Note store GC timeout?", "30000", + NoteStoreTimeout = ask("13. Note store GC timeout?", "30000", fun verify_timeout/1), - NetIfMod = ask("13. Which network interface module shall be used?", + NetIfMod = ask("14. Which network interface module shall be used?", "snmpm_net_if", fun verify_module/1), - NetIfVerb = ask("14. Network interface verbosity " + NetIfVerb = ask("15. Network interface verbosity " "(silence/info/log/debug/trace)?", "silence", fun verify_verbosity/1), - NetIfBindTo = ask("15. Bind the manager IP address " + NetIfBindTo = ask("16. Bind the manager IP address " "(true/false)?", "false", fun verify_bool/1), - NetIfNoReuse = ask("16. Shall the manager IP address and port " + NetIfNoReuse = ask("17. Shall the manager IP address and port " "be not reusable (true/false)?", "false", fun verify_bool/1), NetIfRecbuf = - case ask("17. Receive buffer size of the manager (in bytes) " + case ask("18. Receive buffer size of the manager (in bytes) " "(default/pos integer)?", "default", fun verify_netif_recbuf/1) of default -> @@ -684,7 +689,7 @@ config_manager_sys() -> [{recbuf, RecBufSz}] end, NetIfSndbuf = - case ask("18. Send buffer size of the manager (in bytes) " + case ask("19. Send buffer size of the manager (in bytes) " "(default/pos integer)?", "default", fun verify_netif_sndbuf/1) of default -> @@ -700,28 +705,28 @@ config_manager_sys() -> {verbosity, NetIfVerb}, {options, NetIfOpts}], ATL = - case ask("19. Shall the manager use an audit trail log " + case ask("20. Shall the manager use an audit trail log " "(y/n)?", "n", fun verify_yes_or_no/1) of yes -> - ATLType = ask("19b. Audit trail log type " + ATLType = ask("20b. Audit trail log type " "(write/read_write)?", "read_write", fun verify_atl_type/1), - ATLDir = ask("19c. Where to store the " + ATLDir = ask("20c. Where to store the " "audit trail log?", DefDir, fun verify_dir/1), - ATLMaxFiles = ask("19d. Max number of files?", + ATLMaxFiles = ask("20d. Max number of files?", "10", fun verify_pos_integer/1), - ATLMaxBytes = ask("19e. Max size (in bytes) " + ATLMaxBytes = ask("20e. Max size (in bytes) " "of each file?", "10240", fun verify_pos_integer/1), ATLSize = {ATLMaxBytes, ATLMaxFiles}, - ATLRepair = ask("19f. Audit trail log repair " + ATLRepair = ask("20f. Audit trail log repair " "(true/false/truncate/snmp_repair)?", "true", fun verify_atl_repair/1), - ATLSeqNo = ask("19g. Audit trail log sequence-numbering " + ATLSeqNo = ask("20g. Audit trail log sequence-numbering " "(true/false)?", "false", fun verify_atl_seqno/1), [{audit_trail_log, [{type, ATLType}, @@ -733,14 +738,14 @@ config_manager_sys() -> [] end, DefUser = - case ask("20. Do you wish to assign a default user [yes] or use~n" + case ask("21. Do you wish to assign a default user [yes] or use~n" " the default settings [no] (y/n)?", "n", fun verify_yes_or_no/1) of yes -> - DefUserMod = ask("20b. Default user module?", + DefUserMod = ask("21b. Default user module?", "snmpm_user_default", fun verify_module/1), - DefUserData = ask("20c. Default user data?", "undefined", + DefUserData = ask("21c. Default user data?", "undefined", fun verify_user_data/1), [{def_user_mod, DefUserMod}, {def_user_data, DefUserData}]; @@ -750,11 +755,12 @@ config_manager_sys() -> SysConfig = [{priority, Prio}, {versions, Vsns}, - {config, [{dir, ConfigDir}, - {verbosity, ConfigVerb}, - {db_dir, ConfigDbDir}, - {repair, ConfigDbRepair}, - {auto_save, ConfigDbAutoSave}]}, + {config, [{dir, ConfigDir}, + {db_dir, ConfigDbDir}, + {db_init_error, ConfigDbInitError}, + {repair, ConfigDbRepair}, + {auto_save, ConfigDbAutoSave}, + {verbosity, ConfigVerb}]}, {inform_request_behaviour, IRB}, {mibs, []}, {server, [{timeout, ServerTimeout}, @@ -1069,6 +1075,16 @@ verify_dir(Dir) -> _E -> {error, "invalid directory (not absolute): " ++ Dir} end. + + +verify_db_init_error("terminate") -> + {ok, true}; +verify_db_init_error("create") -> + {ok, create}; +verify_db_init_error("create_db_and_dir") -> + {ok, create_db_and_dir}; +verify_db_init_error(R) -> + {error, "invalid DB init error: " ++ R}. verify_notif_type("trap") -> {ok, trap}; @@ -1164,13 +1180,20 @@ verify_dets_auto_save(I0) -> %% I know that this is a little of the edge, but... +verify_module(M) when is_atom(M) -> + {ok, M}; +verify_module(M0) when is_list(M0) -> + {ok, list_to_atom(M0)}; verify_module(M0) -> - case (catch list_to_atom(M0)) of - M when is_atom(M) -> - {ok, M}; - _ -> - {error, "invalid module: " ++ M0} - end. + {error, lists:flatten(io_lib:format("invalid module: ~p", [M0]))}. + +%% verify_module(M0) -> +%% case (catch list_to_atom(M0)) of +%% M when is_atom(M) -> +%% {ok, M}; +%% _ -> +%% {error, "invalid module: " ++ M0} +%% end. verify_agent_type("master") -> @@ -2168,6 +2191,8 @@ write_sys_config_file_agent_opt(Fid, {config, Opts}) -> ok = io:format(Fid, "}", []); write_sys_config_file_agent_opt(Fid, {db_dir, Dir}) -> ok = io:format(Fid, " {db_dir, \"~s\"}", [Dir]); +write_sys_config_file_agent_opt(Fid, {db_init_error, Action}) -> + ok = io:format(Fid, " {db_init_error, ~w}", [Action]); write_sys_config_file_agent_opt(Fid, {mib_storage, ets}) -> ok = io:format(Fid, " {mib_storage, ets}", []); write_sys_config_file_agent_opt(Fid, {mib_storage, {dets, Dir}}) -> @@ -2344,6 +2369,8 @@ write_sys_config_file_manager_config_opt(Fid, {dir, Dir}) -> ok = io:format(Fid, "{dir, \"~s\"}", [Dir]); write_sys_config_file_manager_config_opt(Fid, {db_dir, Dir}) -> ok = io:format(Fid, "{db_dir, \"~s\"}", [Dir]); +write_sys_config_file_manager_config_opt(Fid, {db_init_error, Action}) -> + ok = io:format(Fid, "{db_init_error, ~w}", [Action]); write_sys_config_file_manager_config_opt(Fid, {repair, Rep}) -> ok = io:format(Fid, "{repair, ~w}", [Rep]); write_sys_config_file_manager_config_opt(Fid, {auto_save, As}) -> diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 7e683e315a..b7d34eb198 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -34,6 +34,7 @@ %% all_tcs - misc app_info/1, info_test/1, + create_local_db_dir/1, %% all_tcs - test_v1 simple/1, @@ -1506,7 +1507,8 @@ finish_misc(Config) -> misc_cases() -> [ app_info, - info_test + info_test, + create_local_db_dir ]. app_info(suite) -> []; @@ -1539,7 +1541,75 @@ app_dir(App) -> "undefined" end. +create_local_db_dir(Config) when is_list(Config) -> + ?P(create_local_db_dir), + DataDir = snmp_test_lib:lookup(data_dir, Config), + T = erlang:now(), + [As,Bs,Cs] = [integer_to_list(I) || I <- tuple_to_list(T)], + DbDir = filename:join([DataDir, As, Bs, Cs]), + ok = del_dir(DbDir, 3), + Name = list_to_atom(atom_to_list(create_local_db_dir) + ++"-"++As++"-"++Bs++"-"++Cs), + Pa = filename:dirname(code:which(?MODULE)), + {ok,Node} = ?t:start_node(Name, slave, [{args, "-pa "++Pa}]), + + %% first start with a nonexisting DbDir + Fun1 = fun() -> + false = filelib:is_dir(DbDir), + process_flag(trap_exit,true), + {error, {error, {failed_open_dets, {file_error, _, _}}}} = + snmpa_local_db:start_link(normal, DbDir, [{verbosity,trace}]), + false = filelib:is_dir(DbDir), + {ok, not_found} + end, + {ok, not_found} = nodecall(Node, Fun1), + %% now start with a nonexisting DbDir but pass the + %% create_local_db_dir option as well + Fun2 = fun() -> + false = filelib:is_dir(DbDir), + process_flag(trap_exit,true), + {ok, _Pid} = + snmpa_local_db:start_link(normal, DbDir, + create_db_and_dir, [{verbosity,trace}]), + snmpa_local_db:stop(), + true = filelib:is_dir(DbDir), + {ok, found} + end, + {ok, found} = nodecall(Node, Fun2), + %% cleanup + ?t:stop_node(Node), + ok = del_dir(DbDir, 3), + ok. + +nodecall(Node, Fun) -> + Parent = self(), + Ref = make_ref(), + spawn_link(Node, + fun() -> + Res = Fun(), + unlink(Parent), + Parent ! {Ref, Res} + end), + receive + {Ref, Res} -> + Res + end. +del_dir(_Dir, 0) -> + ok; +del_dir(Dir, Depth) -> + case filelib:is_dir(Dir) of + true -> + {ok, Files} = file:list_dir(Dir), + lists:map(fun(F) -> + Nm = filename:join(Dir,F), + ok = file:delete(Nm) + end, Files), + ok = file:del_dir(Dir), + del_dir(filename:dirname(Dir), Depth-1); + false -> + ok + end. %v1_cases() -> [loop_mib]; v1_cases() -> diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl index 3192fe1b40..7b9924b83c 100644 --- a/lib/snmp/test/snmp_manager_config_test.erl +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. 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 @@ -57,6 +57,7 @@ start_with_invalid_users_conf_file1/1, start_with_invalid_agents_conf_file1/1, start_with_invalid_usm_conf_file1/1, + start_with_create_db_and_dir_opt/1, @@ -139,8 +140,13 @@ init_per_testcase(Case, Config) when is_list(Config) -> file:make_dir(MgrTopDir = filename:join(CaseTopDir, "manager/")), ?line ok = file:make_dir(MgrConfDir = filename:join(MgrTopDir, "conf/")), - ?line ok = - file:make_dir(MgrDbDir = filename:join(MgrTopDir, "db/")), + MgrDbDir = filename:join(MgrTopDir, "db/"), + case Case of + start_with_create_db_and_dir_opt -> + ok; + _ -> + ?line ok = file:make_dir(MgrDbDir) + end, ?line ok = file:make_dir(MgrLogDir = filename:join(MgrTopDir, "log/")), [{case_top_dir, CaseTopDir}, @@ -174,6 +180,7 @@ groups() -> start_without_mandatory_opts2, start_with_all_valid_opts, start_with_unknown_opts, start_with_incorrect_opts, + start_with_create_db_and_dir_opt, start_with_invalid_manager_conf_file1, start_with_invalid_users_conf_file1, start_with_invalid_agents_conf_file1, @@ -332,7 +339,8 @@ start_with_all_valid_opts(Conf) when is_list(Conf) -> {no_reuse, false}]}], ServerOpts = [{timeout, 10000}, {verbosity, trace}], NoteStoreOpts = [{timeout, 20000}, {verbosity, trace}], - ConfigOpts = [{dir, ConfDir}, {verbosity, trace}, {db_dir, DbDir}], + ConfigOpts = [{dir, ConfDir}, {verbosity, trace}, + {db_dir, DbDir}, {db_init_error, create}], Mibs = [join(StdMibDir, "SNMP-NOTIFICATION-MIB"), join(StdMibDir, "SNMP-USER-BASED-SM-MIB")], Prio = normal, @@ -1674,7 +1682,34 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> %% --- %% +start_with_create_db_and_dir_opt(suite) -> []; +start_with_create_db_and_dir_opt(doc) -> + "Start the snmp manager config process with the\n" + "create_db_and_dir option."; +start_with_create_db_and_dir_opt(Conf) when is_list(Conf) -> + put(tname, swcdado), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + true = not filelib:is_dir(DbDir) and not filelib:is_file(DbDir), + write_manager_conf(ConfDir), + + p("verify nonexistent db_dir"), + ConfigOpts01 = [{verbosity,trace}, {dir, ConfDir}, {db_dir, DbDir}], + {error, Reason01} = config_start([{config, ConfigOpts01}]), + p("nonexistent db_dir res: ~p", [Reason01]), + {invalid_conf_db_dir, _, not_found} = Reason01, + p("verify nonexistent db_dir gets created"), + ConfigOpts02 = [{db_init_error, create_db_and_dir} | ConfigOpts01], + {ok, _Pid} = config_start([{config, ConfigOpts02}]), + true = filelib:is_dir(DbDir), + p("verified: nonexistent db_dir was correctly created"), + ok = config_stop(), + + p("done"), + ok. %% %% --- diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 2164121e86..70f7c2b19a 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.24.2 +SNMP_VSN = 4.25 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" |