aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/snmp')
-rw-r--r--lib/snmp/doc/src/notes.xml128
-rw-r--r--lib/snmp/doc/src/snmp_app.xml7
-rw-r--r--lib/snmp/doc/src/snmp_config.xml9
-rw-r--r--lib/snmp/doc/src/snmpa.xml75
-rw-r--r--lib/snmp/doc/src/snmpa_mib_data.xml2
-rw-r--r--lib/snmp/src/agent/snmpa.erl70
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl32
-rw-r--r--lib/snmp/src/agent/snmpa_local_db.erl8
-rw-r--r--lib/snmp/src/agent/snmpa_mib.erl49
-rw-r--r--lib/snmp/src/agent/snmpa_supervisor.erl2
-rw-r--r--lib/snmp/src/app/snmp.appup.src64
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl31
-rw-r--r--lib/snmp/src/misc/snmp_config.erl187
-rw-r--r--lib/snmp/test/snmp_agent_mibs_test.erl22
-rw-r--r--lib/snmp/test/snmp_agent_test.erl146
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl74
-rw-r--r--lib/snmp/test/snmp_manager_config_test.erl43
17 files changed, 652 insertions, 297 deletions
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 646e3027d6..68743e60aa 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -36,7 +36,7 @@
<section>
<title>SNMP Development Toolkit 4.25</title>
<p>Version 4.25 supports code replacement in runtime from/to
- version 4.24.1, 4.24, 4.23.1 and 4.23. </p>
+ version 4.24.2, 4.24.1, 4.24, 4.23.1 and 4.23. </p>
<section>
<title>Improvements and new features</title>
@@ -46,6 +46,23 @@
<list type="bulleted">
<item>
+ <p>[agent] 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>
+
+ <item>
<p>[manager] Improved handling of unexpected return values from
<seealso marker="snmpm_user">snmpm_user</seealso>
callback functions. </p>
@@ -65,57 +82,102 @@
<!--
<list type="bulleted">
<item>
- <p>[agent] Reading the value of the vacmViewTreeFamilyMask returns
- it in the wrong (internal bitlist) format. </p>
- <p>The vacmViewTreeFamilyMask is defined as a bit string in the MIB
- (OCTET STRING). Internally a bitlist (list of 1's and 0's,
- see <seealso marker="snmp_agent_config_files#vacm">vacm config file</seealso>
- for more info) is used.
- However, the MIB implementation assumed the latter, effectively
- rendering all attempts to read/set masks via SNMP unsuccessful. </p>
- <p>Since the mask is used in hot paths (e.g. access permission checks
- for each SNMP operation, the bitlist representation of the mask has
- benefits (e.g. faster processing). Reading/writing the view mask
- objects is less time-critical. Therefore, to fix the issue, convert
- between the bitlist (internal) representation and bitstring
- (external) when the vacmViewTreeFamilyMask objects are accessed. </p>
- <p>Also, the check of the vacm config file was invalid with
- regard to the mask value. It was assumed to be a proper oid, which
- is not strictly the case (see bitlist above). </p>
- <p>Own Id: OTP-11177</p>
- <p>Stefan Zegenhagen</p>
+ <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>[agent] The counter increment function in the local-db was
- incorrect. It did not handle counter wrap correctly. </p>
- <p>Own Id: OTP-11192</p>
+ <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>
+
<section>
- <title>Incompatibilities</title>
+ <title>Improvements and new features</title>
<!--
<p>-</p>
-->
<list type="bulleted">
<item>
- <p>[manager] The
- <seealso marker="snmpm_user">snmpm_user</seealso>
- callback functions are no longer allowed to "return" via
- exit or throw. </p>
- <p>Own Id: OTP-11307</p>
+ <p>[agent] Improved documentation for the functions for
+ loading and unloading mibs,
+ see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
+ <seealso marker="snmpa#unload_mibs">unload_mibs</seealso> for
+ more info. </p>
+ <p>Also added new functions for loading and unloading a single mib,
+ see <seealso marker="snmpa#load_mib">load_mib</seealso> and
+ <seealso marker="snmpa#unload_mib">unload_mib</seealso> for
+ more info. </p>
+ <p>Own Id: OTP-11216</p>
</item>
</list>
+
</section>
- </section> <!-- 4.25 -->
+ <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.24.2 -->
<section>
@@ -232,7 +294,7 @@
<seealso marker="snmpa_mib_storage">mib storage</seealso>.
At present there are three simple modules
(<c>snmpa_mib_storage_ets</c>, <c>snmpa_mib_storage_dets</c> and
- <c>snmpa_mib_storage_mnesia</c>) implement�ng this behaviour,
+ <c>snmpa_mib_storage_mnesia</c>) implementing this behaviour,
provided with the app. </p>
<p>A config option for the (agent)
<seealso marker="snmp_config#agent_mib_storage">mib storage</seealso>
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/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index 86fde03205..77146f3a89 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -245,29 +245,75 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
This function is used to convert to the old (pre-4.4) info
format. </p>
+ <marker id="load_mib"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>load_mib(Mib) -> ok | {error, Reason}</name>
+ <name>load_mib(Agent, Mib) -> ok | {error, Reason}</name>
+ <fsummary>Load single MIB into the agent</fsummary>
+ <type>
+ <v>Agent = pid() | atom()</v>
+ <v>MibName = string()</v>
+ <v>Reason = already_loaded | term()</v>
+ </type>
+ <desc>
+ <p>Load a single <c>Mib</c> into an agent. The <c>MibName</c>
+ is the name of the Mib, including the path to where the compiled
+ mib is found. For example: </p>
+ <code type="none">
+ Dir = code:priv_dir(my_app) ++ "/mibs/",
+ snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").
+ </code>
+
<marker id="load_mibs"></marker>
</desc>
</func>
<func>
<name>load_mibs(Mibs) -> ok | {error, Reason}</name>
- <name>load_mibs(Agent,Mibs) -> ok | {error, Reason}</name>
+ <name>load_mibs(Mibs, Force) -> ok | {error, Reason}</name>
+ <name>load_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
+ <name>load_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
<fsummary>Load MIBs into the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
<v>Mibs = [MibName]</v>
+ <v>Force = boolean()</v>
<v>MibName = string()</v>
- <v>Reason = term()</v>
+ <v>Reason = {'load aborted at', MibName, InternalReason}</v>
+ <v>InternalReason = already_loaded | term()</v>
</type>
<desc>
- <p>Loads <c>Mibs</c> into an agent. If the agent cannot load
- all MIBs, it will indicate where loading was aborted. The
- <c>MibName</c> is the name of the Mib, including the path to
- where the compiled mib is found. For example,</p>
- <code type="none">
+ <p>Load <c>Mibs</c> into an agent. If the agent cannot load all
+ MIBs (the default value of the <c>Force</c> argument is <c>false</c>),
+ it will indicate where loading was aborted. The <c>MibName</c>
+ is the name of the Mib, including the path to where the compiled
+ mib is found. For example,</p>
+ <code type="none">
Dir = code:priv_dir(my_app) ++ "/mibs/",
snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).
</code>
+ <p>If <c>Force = true</c> then the agent will continue attempting
+ to load each mib even after failing to load a previous mib. Use with
+ care. </p>
+
+ <marker id="unload_mib"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>unload_mib(Mib) -> ok | {error, Reason}</name>
+ <name>unload_mib(Agent, Mib) -> ok | {error, Reason}</name>
+ <fsummary>Unload single MIB from the agent</fsummary>
+ <type>
+ <v>Agent = pid() | atom()</v>
+ <v>MibName = string()</v>
+ <v>Reason = not_loaded | term()</v>
+ </type>
+ <desc>
+ <p>Unload a single <c>Mib</c> from an agent. </p>
<marker id="unload_mibs"></marker>
</desc>
@@ -275,16 +321,25 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<func>
<name>unload_mibs(Mibs) -> ok | {error, Reason}</name>
- <name>unload_mibs(Agent,Mibs) -> ok | {error, Reason}</name>
+ <name>unload_mibs(Mibs, Force) -> ok | {error, Reason}</name>
+ <name>unload_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
+ <name>unload_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
<fsummary>Unload MIBs from the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
<v>Mibs = [MibName]</v>
+ <v>Force = boolean()</v>
<v>MibName = string()</v>
+ <v>Reason = {'unload aborted at', MibName, InternalReason}</v>
+ <v>InternalReason = not_loaded | term()</v>
</type>
<desc>
- <p>Unloads MIBs into an agent. If it cannot unload all MIBs,
- it will indicate where unloading was aborted. </p>
+ <p>Unload <c>Mibs</c> from an agent. If it cannot unload all MIBs
+ (the default value of the <c>Force</c> argument is <c>false</c>),
+ it will indicate where unloading was aborted. </p>
+ <p>If <c>Force = true</c> then the agent will continue attempting
+ to unload each mib even after failing to unload a previous mib.
+ Use with care. </p>
<marker id="which_mibs"></marker>
</desc>
diff --git a/lib/snmp/doc/src/snmpa_mib_data.xml b/lib/snmp/doc/src/snmpa_mib_data.xml
index ff07a03b98..c1ea0a91f9 100644
--- a/lib/snmp/doc/src/snmpa_mib_data.xml
+++ b/lib/snmp/doc/src/snmpa_mib_data.xml
@@ -380,7 +380,7 @@
<desc>
<p>Perform a code-change (upgrade or downgrade). </p>
<p>See
- <seealso marker="gen_server">gen_server</seealso>
+ <seealso marker="stdlib:gen_server">gen_server</seealso>
for more info regarding the <c>Vsn</c> and <c>Extra</c> arguments. </p>
</desc>
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl
index 14b93439df..a95e41ea42 100644
--- a/lib/snmp/src/agent/snmpa.erl
+++ b/lib/snmp/src/agent/snmpa.erl
@@ -39,8 +39,10 @@
enum_to_int/2, enum_to_int/3,
info/0, info/1, old_info_format/1,
- load_mibs/1, load_mibs/2,
- unload_mibs/1, unload_mibs/2,
+ load_mib/1, load_mib/2,
+ load_mibs/1, load_mibs/2, load_mibs/3,
+ unload_mib/1, unload_mib/2,
+ unload_mibs/1, unload_mibs/2, unload_mibs/3,
which_mibs/0, which_mibs/1,
whereis_mib/1, whereis_mib/2,
dump_mibs/0, dump_mibs/1,
@@ -300,19 +302,75 @@ backup(Agent, BackupDir) ->
dump_mibs() -> snmpa_agent:dump_mibs(snmp_master_agent).
dump_mibs(File) -> snmpa_agent:dump_mibs(snmp_master_agent, File).
+
+load_mib(Mib) ->
+ load_mib(snmp_master_agent, Mib).
+
+-spec load_mib(Agent :: pid() | atom(), Mib :: string()) ->
+ ok | {error, Reason :: already_loaded | term()}.
+
+load_mib(Agent, Mib) ->
+ case load_mibs(Agent, [Mib]) of
+ {error, {'load aborted at', Mib, Reason}} ->
+ {error, Reason};
+ Else ->
+ Else
+ end.
+
load_mibs(Mibs) ->
- load_mibs(snmp_master_agent, Mibs).
+ load_mibs(snmp_master_agent, Mibs, false).
load_mibs(Agent, Mibs) when is_list(Mibs) ->
- snmpa_agent:load_mibs(Agent, Mibs).
+ snmpa_agent:load_mibs(Agent, Mibs, false);
+load_mibs(Mibs, Force)
+ when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ load_mibs(snmp_master_agent, Mibs, Force).
+
+-spec load_mibs(Agent :: pid() | atom(),
+ Mibs :: [MibName :: string()],
+ Force :: boolean()) ->
+ ok | {error, {'load aborted at', MibName :: string(), InternalReason :: already_loaded | term()}}.
+
+load_mibs(Agent, Mibs, Force)
+ when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ snmpa_agent:load_mibs(Agent, Mibs, Force).
+
+
+unload_mib(Mib) ->
+ unload_mib(snmp_master_agent, Mib).
+
+-spec unload_mib(Agent :: pid() | atom(), Mib :: string()) ->
+ ok | {error, Reason :: not_loaded | term()}.
+
+unload_mib(Agent, Mib) ->
+ case unload_mibs(Agent, [Mib]) of
+ {error, {'unload aborted at', Mib, Reason}} ->
+ {error, Reason};
+ Else ->
+ Else
+ end.
unload_mibs(Mibs) ->
- unload_mibs(snmp_master_agent, Mibs).
+ unload_mibs(snmp_master_agent, Mibs, false).
unload_mibs(Agent, Mibs) when is_list(Mibs) ->
- snmpa_agent:unload_mibs(Agent, Mibs).
+ snmpa_agent:unload_mibs(Agent, Mibs);
+unload_mibs(Mibs, Force)
+ when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ unload_mibs(snmp_master_agent, Mibs, Force).
+
+-spec unload_mibs(Agent :: pid() | atom(),
+ Mibs :: [MibName :: string()],
+ Force :: boolean()) ->
+ ok | {error, {'unload aborted at', MibName :: string(), InternalReason :: not_loaded | term()}}.
+
+unload_mibs(Agent, Mibs, Force)
+ when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ snmpa_agent:unload_mibs(Agent, Mibs, Force).
+
which_mibs() -> which_mibs(snmp_master_agent).
which_mibs(Agent) -> snmpa_agent:which_mibs(Agent).
+
whereis_mib(Mib) ->
whereis_mib(snmp_master_agent, Mib).
whereis_mib(Agent, Mib) when is_atom(Mib) ->
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index c267ce5a70..9bed6e554e 100644
--- a/lib/snmp/src/agent/snmpa_agent.erl
+++ b/lib/snmp/src/agent/snmpa_agent.erl
@@ -28,7 +28,8 @@
%% External exports
-export([start_link/4, start_link/5, stop/1]).
-export([subagent_set/2,
- load_mibs/2, unload_mibs/2, which_mibs/1, whereis_mib/2, info/1,
+ load_mibs/3, unload_mibs/3,
+ which_mibs/1, whereis_mib/2, info/1,
register_subagent/3, unregister_subagent/2,
send_notification/3,
register_notification_filter/5,
@@ -71,7 +72,8 @@
handle_pdu/8, worker/2, worker_loop/1,
do_send_trap/7, do_send_trap/8]).
%% <BACKWARD-COMPAT>
--export([handle_pdu/7]).
+-export([handle_pdu/7,
+ load_mibs/2, unload_mibs/2]).
%% </BACKWARD-COMPAT>
-include("snmpa_internal.hrl").
@@ -528,12 +530,22 @@ subagent_set(SubAgent, Arguments) ->
%% Called by administrator (not agent; deadlock would occur)
+%% <BACKWARD-COMPAT>
load_mibs(Agent, Mibs) ->
- call(Agent, {load_mibs, Mibs}).
+ load_mibs(Agent, Mibs, false).
+%% </BACKWARD-COMPAT>
+
+load_mibs(Agent, Mibs, Force) ->
+ call(Agent, {load_mibs, Mibs, Force}).
%% Called by administrator (not agent; deadlock would occur)
+%% <BACKWARD-COMPAT>
unload_mibs(Agent, Mibs) ->
- call(Agent, {unload_mibs, Mibs}).
+ unload_mibs(Agent, Mibs, false).
+%% </BACKWARD-COMPAT>
+
+unload_mibs(Agent, Mibs, Force) ->
+ call(Agent, {unload_mibs, Mibs, Force}).
which_mibs(Agent) ->
call(Agent, which_mibs).
@@ -1216,13 +1228,25 @@ handle_call({unregister_subagent, SubTreeOid}, _From, S) ->
end,
{reply, Reply, S};
+%% <BACKWARD-COMPAT>
handle_call({load_mibs, Mibs}, _From, S) ->
?vlog("load mibs ~p", [Mibs]),
{reply, snmpa_mib:load_mibs(get(mibserver), Mibs), S};
+%% </BACKWARD-COMPAT>
+
+handle_call({load_mibs, Mibs, Force}, _From, S) ->
+ ?vlog("[~w] load mibs ~p", [Force, Mibs]),
+ {reply, snmpa_mib:load_mibs(get(mibserver), Mibs, Force), S};
+%% <BACKWARD-COMPAT>
handle_call({unload_mibs, Mibs}, _From, S) ->
?vlog("unload mibs ~p", [Mibs]),
{reply, snmpa_mib:unload_mibs(get(mibserver), Mibs), S};
+%% </BACKWARD-COMPAT>
+
+handle_call({unload_mibs, Mibs, Force}, _From, S) ->
+ ?vlog("[~w] unload mibs ~p", [Force, Mibs]),
+ {reply, snmpa_mib:unload_mibs(get(mibserver), Mibs, Force), S};
handle_call(which_mibs, _From, S) ->
?vlog("which mibs", []),
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_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl
index 031309b990..5b523447c5 100644
--- a/lib/snmp/src/agent/snmpa_mib.erl
+++ b/lib/snmp/src/agent/snmpa_mib.erl
@@ -26,7 +26,7 @@
%% External exports
-export([start_link/3, stop/1,
lookup/2, next/3, which_mib/2, which_mibs/1, whereis_mib/2,
- load_mibs/2, unload_mibs/2,
+ load_mibs/3, unload_mibs/3,
register_subagent/3, unregister_subagent/2, info/1, info/2,
verbosity/2, dump/1, dump/2,
backup/2,
@@ -39,6 +39,10 @@
which_cache_size/1
]).
+%% <BACKWARD-COMPAT>
+-export([load_mibs/2, unload_mibs/2]).
+%% </BACKWARD-COMPAT>
+
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]).
@@ -182,19 +186,32 @@ next(MibServer, Oid, MibView) ->
%%----------------------------------------------------------------------
%% Purpose: Loads mibs into the mib process.
%% Args: Mibs is a list of Filenames (compiled mibs).
+%% Force is a boolean
%% Returns: ok | {error, Reason}
%%----------------------------------------------------------------------
+
+%% <BACKWARD-COMPAT>
load_mibs(MibServer, Mibs) ->
- call(MibServer, {load_mibs, Mibs}).
+ load_mibs(MibServer, Mibs, false).
+%% </BACKWARD-COMPAT>
+
+load_mibs(MibServer, Mibs, Force) ->
+ call(MibServer, {load_mibs, Mibs, Force}).
%%----------------------------------------------------------------------
%% Purpose: Loads mibs into the mib process.
%% Args: Mibs is a list of Filenames (compiled mibs).
+%% Force is a boolean
%% Returns: ok | {error, Reason}
%%----------------------------------------------------------------------
+%% <BACKWARD-COMPAT>
unload_mibs(MibServer, Mibs) ->
- call(MibServer, {unload_mibs, Mibs}).
+ unload_mibs(MibServer, Mibs, false).
+%% </BACKWARD-COMPAT>
+
+unload_mibs(MibServer, Mibs, Force) ->
+ call(MibServer, {unload_mibs, Mibs, Force}).
%%----------------------------------------------------------------------
@@ -323,10 +340,6 @@ do_init(Prio, Mibs, Opts) ->
%% Returns: {ok, NewMibData} | {'aborted at', Mib, NewData, Reason}
%% Args: Operation is load_mib | unload_mib.
%%----------------------------------------------------------------------
-mib_operations(Mod, Operation, Mibs, Data, MeOverride, TeOverride) ->
- mib_operations(Mod, Operation, Mibs, Data, MeOverride, TeOverride, false).
-
-
mib_operations(_Mod, _Operation, [], Data, _MeOverride, _TeOverride, _Force) ->
{ok, Data};
mib_operations(Mod, Operation, [Mib|Mibs], Data0, MeOverride, TeOverride, Force) ->
@@ -451,18 +464,23 @@ handle_call({next, Oid, MibView}, _From,
?vdebug("next -> Reply: ~p", [Reply]),
{reply, Reply, NewState};
-handle_call({load_mibs, Mibs}, _From,
+%% <BACKWARD-COMPAT>
+handle_call({load_mibs, Mibs}, From, State) ->
+ handle_call({load_mibs, Mibs, false}, From, State);
+%% </BACKWARD-COMPAT>
+
+handle_call({load_mibs, Mibs, Force}, _From,
#state{data = Data,
teo = TeOverride,
meo = MeOverride,
cache = Cache,
data_mod = Mod} = State) ->
- ?vlog("load mibs ~p",[Mibs]),
+ ?vlog("[~w] load mibs ~p", [Force, Mibs]),
%% Invalidate cache
NewCache = maybe_invalidate_cache(Cache),
{NData, Reply} =
case (catch mib_operations(Mod, load_mib, Mibs, Data,
- MeOverride, TeOverride)) of
+ MeOverride, TeOverride, Force)) of
{'aborted at', Mib, NewData, Reason} ->
?vlog("aborted at ~p for reason ~p",[Mib,Reason]),
{NewData, {error, {'load aborted at', Mib, Reason}}};
@@ -472,19 +490,24 @@ handle_call({load_mibs, Mibs}, _From,
Mod:sync(NData),
{reply, Reply, State#state{data = NData, cache = NewCache}};
-handle_call({unload_mibs, Mibs}, _From,
+%% <BACKWARD-COMPAT>
+handle_call({unload_mibs, Mibs}, From, State) ->
+ handle_call({unload_mibs, Mibs, false}, From, State);
+%% </BACKWARD-COMPAT>
+
+handle_call({unload_mibs, Mibs, Force}, _From,
#state{data = Data,
teo = TeOverride,
meo = MeOverride,
cache = Cache,
data_mod = Mod} = State) ->
- ?vlog("unload mibs ~p",[Mibs]),
+ ?vlog("[~w] unload mibs ~p", [Force, Mibs]),
%% Invalidate cache
NewCache = maybe_invalidate_cache(Cache),
%% Unload mib(s)
{NData, Reply} =
case (catch mib_operations(Mod, unload_mib, Mibs, Data,
- MeOverride, TeOverride)) of
+ MeOverride, TeOverride, Force)) of
{'aborted at', Mib, NewData, Reason} ->
?vlog("aborted at ~p for reason ~p", [Mib,Reason]),
{NewData, {error, {'unload aborted at', Mib, Reason}}};
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 7bd50c2c4d..e1bf7692b3 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -29,35 +29,9 @@
%% {add_module, snmpm_net_if_mt}
[
- {"4.24.2",
- [
- {load_module, snmp, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm_user, soft_purge, soft_purge, [snmp, snmpm]},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user]}
- ]
- },
- {"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, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm_user, soft_purge, soft_purge, [snmp, snmpm]},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpa_local_db, 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}]}
],
@@ -68,35 +42,9 @@
%% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
[
- {"4.24.2",
- [
- {load_module, snmp, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm_user, soft_purge, soft_purge, [snmp, snmpm]},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user]}
- ]
- },
- {"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, soft_purge, soft_purge, []},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge, [snmp]},
- {load_module, snmpm_user, soft_purge, soft_purge, [snmp, snmpm]},
- {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user]},
- {update, snmpa_local_db, 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_mibs_test.erl b/lib/snmp/test/snmp_agent_mibs_test.erl
index 248fe7d83e..f7dae64e3f 100644
--- a/lib/snmp/test/snmp_agent_mibs_test.erl
+++ b/lib/snmp/test/snmp_agent_mibs_test.erl
@@ -238,6 +238,8 @@ start_and_stop(Config) when is_list(Config) ->
load_unload(suite) -> [];
load_unload(Config) when is_list(Config) ->
+ ?DBG("load_unload -> start", []),
+
Prio = normal,
Verbosity = log,
MibDir = ?config(data_dir, Config),
@@ -253,8 +255,10 @@ load_unload(Config) when is_list(Config) ->
?line ok = load_mibs(MibsPid, MibDir, ["Test2"]),
?line ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]),
- ?DBG("load_unload -> load one already loaded mib", []),
- ?line {error, _} = load_mibs(MibsPid, MibDir, ["Test2"]),
+ ?DBG("load_unload -> try load one *already loaded* mib", []),
+ EMib = join(MibDir, "Test2"),
+ ?line {error, {'load aborted at', EMib, already_loaded}} =
+ load_mibs(MibsPid, MibDir, ["Test2"]),
?DBG("load_unload -> load 2 not already loaded mibs", []),
?line ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
@@ -266,7 +270,8 @@ load_unload(Config) when is_list(Config) ->
?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
?DBG("load_unload -> try unload two loaded mibs and one not loaded", []),
- ?line {error, _} = unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]),
+ ?line {error, {'unload aborted at', "Test2", not_loaded}} =
+ unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]),
?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]),
?DBG("load_unload -> unload the remaining loaded mib", []),
@@ -279,6 +284,7 @@ load_unload(Config) when is_list(Config) ->
?DBG("load_unload -> stop symbolic store", []),
?line sym_stop(),
+ ?DBG("load_unload -> done", []),
ok.
@@ -691,10 +697,16 @@ mibs_info(Pid) ->
load_mibs(Pid, Dir, Mibs0) ->
Mibs = [join(Dir, Mib) || Mib <- Mibs0],
- snmpa_mib:load_mibs(Pid, Mibs).
+ Res = snmpa_mib:load_mibs(Pid, Mibs),
+ %% ?DBG("load_mibs -> "
+ %% "~n Res: ~p", [Res]),
+ Res.
unload_mibs(Pid, Mibs) ->
- snmpa_mib:unload_mibs(Pid, Mibs).
+ Res = snmpa_mib:unload_mibs(Pid, Mibs),
+ %% ?DBG("unload_mibs -> "
+ %% "~n Res: ~p", [Res]),
+ Res.
verify_loaded_mibs(Pid, Dir, ExpectedMibs0) ->
ExpectedMibs = [join(Dir, Mib) || Mib <- ExpectedMibs0],
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 6fe97ccd25..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,
@@ -554,7 +555,7 @@ init_per_suite(Config0) when is_list(Config0) ->
%% Mib-dirs
MibDir = snmp_test_lib:lookup(data_dir, Config2),
- StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+ StdMibDir = join([code:priv_dir(snmp), "mibs"]),
Config3 = [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2],
@@ -748,21 +749,21 @@ init_per_testcase2(Case, Config) ->
CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
%% Create agent top-dir(s)
- AgentTopDir = filename:join([CaseTopDir, agent]),
+ AgentTopDir = join([CaseTopDir, agent]),
ok = file:make_dir(AgentTopDir),
- AgentConfDir = filename:join([AgentTopDir, config]),
+ AgentConfDir = join([AgentTopDir, config]),
ok = file:make_dir(AgentConfDir),
- AgentDbDir = filename:join([AgentTopDir, db]),
+ AgentDbDir = join([AgentTopDir, db]),
ok = file:make_dir(AgentDbDir),
- AgentLogDir = filename:join([AgentTopDir, log]),
+ AgentLogDir = join([AgentTopDir, log]),
ok = file:make_dir(AgentLogDir),
%% Create sub-agent top-dir(s)
- SubAgentTopDir = filename:join([CaseTopDir, sub_agent]),
+ SubAgentTopDir = join([CaseTopDir, sub_agent]),
ok = file:make_dir(SubAgentTopDir),
%% Create manager top-dir(s)
- ManagerTopDir = filename:join([CaseTopDir, manager]),
+ ManagerTopDir = join([CaseTopDir, manager]),
ok = file:make_dir(ManagerTopDir),
[{case_top_dir, CaseTopDir},
@@ -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() ->
@@ -1738,19 +1808,19 @@ init_case(Config) ->
load_master(Mib) ->
?DBG("load_master -> entry with"
"~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+ snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety
+ ok = snmpa:load_mib(snmp_master_agent, join(get(mib_dir), Mib)).
load_master_std(Mib) ->
?DBG("load_master_std -> entry with"
"~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+ snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety
+ ok = snmpa:load_mib(snmp_master_agent, join(get(std_mib_dir), Mib)).
unload_master(Mib) ->
?DBG("unload_master -> entry with"
"~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+ ok = snmpa:unload_mib(snmp_master_agent, Mib).
loaded_mibs() ->
?DBG("loaded_mibs -> entry",[]),
@@ -2155,11 +2225,11 @@ subagent(Config) when is_list(Config) ->
try_test(unreg_test),
?P1("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas1")),
try_test(load_test),
?P1("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas1")),
try_test(unreg_test),
?P1("Testing register subagent..."),
rpc:call(SaNode, snmp, register_subagent,
@@ -2355,11 +2425,11 @@ sa_register(Config) when is_list(Config) ->
?P1("Unloading Klas1..."),
?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ snmpa:unload_mib(SA, join(MibDir, "Klas1")),
?P1("Loading SA-MIB..."),
?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ snmpa:load_mib(SA, join(MibDir, "SA-MIB")),
?P1("register subagent..."),
?DBG("sa_register -> register subagent", []),
@@ -2578,7 +2648,7 @@ next_across_sa(Config) when is_list(Config) ->
?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?P1("Loading another subagent mib (Klas1)..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+ ?line ok = snmpa:load_mib(SA, MibDir ++ "Klas1"),
?P1("register subagent..."),
rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
@@ -2590,7 +2660,7 @@ next_across_sa(Config) when is_list(Config) ->
try_test(next_across_sa_test),
?P1("Unloading mib (Klas1)"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ snmpa:unload_mib(SA, join(MibDir, "Klas1")),
rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
try_test(unreg_test),
@@ -2631,25 +2701,25 @@ undo(Config) when is_list(Config) ->
?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?P1("Load Klas3 & Klas4..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas3")),
+ ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas4")),
?P1("Testing undo phase at master agent..."),
try_test(undo_test),
try_test(api_test2),
?P1("Unload Klas3..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas3")),
?P1("Testing bad return values from instrum. funcs..."),
try_test(bad_return),
?P1("Unload Klas4..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas4")),
?P1("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas3")),
+ ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas4")),
?line ok = snmpa:register_subagent(MA, ?klas3, SA),
?line ok = snmpa:register_subagent(MA, ?klas4, SA),
try_test(undo_test),
@@ -6247,8 +6317,8 @@ otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
"OTP-4394 test"),
?line case update_usm(Vsn, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
+ ?line copy_file(join(AgentConfDir, "usm.conf"),
+ join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsn, MgrDir);
false ->
?line ok
@@ -6407,11 +6477,11 @@ otp8395({init, Config}) when is_list(Config) ->
%%
AgentDbDir = ?config(agent_db_dir, Config),
- AgentMnesiaDir = filename:join([AgentDbDir, "mnesia"]),
+ AgentMnesiaDir = join([AgentDbDir, "mnesia"]),
mnesia_init(AgentNode, AgentMnesiaDir),
%% SubAgentDir = ?config(sub_agent_dir, Config),
- %% SubAgentMnesiaDir = filename:join([SubAgentDir, "mnesia"]),
+ %% SubAgentMnesiaDir = join([SubAgentDir, "mnesia"]),
%% mnesia_init(SubAgentNode, SubAgentMnesiaDir),
%% ok = mnesia_create_schema(AgentNode, [AgentNode, SubAgentNode]),
@@ -6541,7 +6611,7 @@ otp8395(Config) when is_list(Config) ->
?SLEEP(1000),
AgentNode = ?config(agent_node, Config),
AgentLogDir = ?config(agent_log_dir, Config),
- OutFile = filename:join([AgentLogDir, "otp8395.txt"]),
+ OutFile = join([AgentLogDir, "otp8395.txt"]),
{ok, LogInfo} = rpc:call(AgentNode, snmpa, log_info, []),
?DBG("otp8395 -> LogInfo: ~p", [LogInfo]),
@@ -6579,7 +6649,7 @@ otp9884({init, Config}) when is_list(Config) ->
%%
AgentDbDir = ?config(agent_db_dir, Config),
- AgentMnesiaDir = filename:join([AgentDbDir, "mnesia"]),
+ AgentMnesiaDir = join([AgentDbDir, "mnesia"]),
mnesia_init(AgentNode, AgentMnesiaDir),
mnesia_create_schema(AgentNode, [AgentNode]),
@@ -6609,8 +6679,8 @@ otp9884({init, Config}) when is_list(Config) ->
ManagerConfDir = ?config(manager_top_dir, Config),
AgentConfDir = ?config(agent_conf_dir, Config),
AgentTopDir = ?config(agent_top_dir, Config),
- AgentBkpDir1 = filename:join([AgentTopDir, backup1]),
- AgentBkpDir2 = filename:join([AgentTopDir, backup2]),
+ AgentBkpDir1 = join([AgentTopDir, backup1]),
+ AgentBkpDir2 = join([AgentTopDir, backup2]),
ok = file:make_dir(AgentBkpDir1),
ok = file:make_dir(AgentBkpDir2),
AgentBkpDirs = [AgentBkpDir1, AgentBkpDir2],
@@ -7105,7 +7175,7 @@ display_log(Config) ->
{value, {_, Node}} ->
LogDir = Dir,
Mibs = [],
- OutFile = filename:join(LogDir, "snmpa_log.txt"),
+ OutFile = join(LogDir, "snmpa_log.txt"),
p("~n"
"========================="
" < Audit Trail Log > "
@@ -7252,6 +7322,14 @@ lists_key1search(Key, List) when is_atom(Key) ->
%% regs() ->
%% lists:sort(registered()).
+%% ------
+
+join(Parts) ->
+ filename:join(Parts).
+
+join(Dir, File) ->
+ filename:join(Dir, File).
+
%% ------
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 7e4b713e56..122289c28e 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -139,31 +139,31 @@ init_all(Config) when is_list(Config) ->
SuiteTopDir = ?config(snmp_suite_top_dir, Config),
?DBG("init_all -> SuiteTopDir ~p", [SuiteTopDir]),
- AgentDir = filename:join(SuiteTopDir, "agent/"),
+ AgentDir = join(SuiteTopDir, "agent/"),
?line ok = file:make_dir(AgentDir),
?DBG("init_all -> AgentDir ~p", [AgentDir]),
- AgentDbDir = filename:join(AgentDir, "db/"),
+ AgentDbDir = join(AgentDir, "db/"),
?line ok = file:make_dir(AgentDbDir),
?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]),
- AgentLogDir = filename:join(AgentDir, "log/"),
+ AgentLogDir = join(AgentDir, "log/"),
?line ok = file:make_dir(AgentLogDir),
?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]),
- AgentConfDir = filename:join(AgentDir, "conf/"),
+ AgentConfDir = join(AgentDir, "conf/"),
?line ok = file:make_dir(AgentConfDir),
?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]),
- MgrDir = filename:join(SuiteTopDir, "mgr/"),
+ MgrDir = join(SuiteTopDir, "mgr/"),
?line ok = file:make_dir(MgrDir),
?DBG("init_all -> MgrDir ~p", [MgrDir]),
- SaDir = filename:join(SuiteTopDir, "sa/"),
+ SaDir = join(SuiteTopDir, "sa/"),
?line ok = file:make_dir(SaDir),
?DBG("init_all -> SaDir ~p", [SaDir]),
- SaDbDir = filename:join(SaDir, "db/"),
+ SaDbDir = join(SaDir, "db/"),
?line ok = file:make_dir(SaDbDir),
?DBG("init_all -> SaDbDir ~p", [SaDbDir]),
@@ -183,11 +183,11 @@ init_all(Config) when is_list(Config) ->
?DBG("init_all -> application mnesia: set_env dir",[]),
?line application_controller:set_env(mnesia, dir,
- filename:join(AgentDbDir, "Mnesia1")),
+ join(AgentDbDir, "Mnesia1")),
?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(SaDir, "Mnesia2")]),
+ [mnesia, dir, join(SaDir, "Mnesia2")]),
?DBG("init_all -> create mnesia schema",[]),
?line ok = mnesia:create_schema([SaNode, node()]),
@@ -253,7 +253,7 @@ init_case(Config) when is_list(Config) ->
MibDir = ?config(mib_dir, Config),
put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ StdM = join(code:priv_dir(snmp), "mibs") ++ "/",
put(std_mib_dir, StdM),
MgrDir = ?config(mgr_dir, Config),
@@ -341,7 +341,7 @@ run(Mod, Func, Args, Opts) ->
Crypto = ?CRYPTO_START(),
?DBG("run -> Crypto: ~p", [Crypto]),
catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ StdM = join(code:priv_dir(snmp), "mibs") ++ "/",
Vsn = get(vsn),
?DBG("run -> config:"
"~n M: ~p"
@@ -763,7 +763,7 @@ start_subagent(SaNode, RegTree, Mib) ->
MA = whereis(snmp_master_agent),
?DBG("start_subagent -> MA: ~p", [MA]),
MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
+ Mib1 = join(MibDir, Mib),
Mod = snmpa_supervisor,
Func = start_sub_agent,
Args = [MA, RegTree, [Mib1]],
@@ -800,28 +800,25 @@ mibs(StdMibDir,MibDir) ->
join(MibDir, "Test2.bin"),
join(MibDir, "TestTrapv2.bin")].
-join(D,F) ->
- filename:join(D,F).
-
%% --- various mib load/unload functions ---
load_master(Mib) ->
?DBG("load_master -> entry with"
"~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+ snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety
+ ok = snmpa:load_mib(snmp_master_agent, join(get(mib_dir), Mib)).
load_master_std(Mib) ->
?DBG("load_master_std -> entry with"
"~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+ snmpa:unload_mib(snmp_master_agent, Mib), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, join(get(std_mib_dir), Mib)).
unload_master(Mib) ->
?DBG("unload_master -> entry with"
"~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+ ok = snmpa:unload_mib(snmp_master_agent, Mib).
loaded_mibs() ->
?DBG("loaded_mibs -> entry",[]),
@@ -1383,8 +1380,8 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp) ->
"test"),
?line case update_usm(Vsns, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
+ ?line copy_file(join(AgentConfDir, "usm.conf"),
+ join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsns, MgrDir);
false ->
?line ok
@@ -1403,9 +1400,9 @@ delete_files(Config) ->
delete_files(_AgentFiles, []) ->
ok;
delete_files(AgentDir, [DirName|DirNames]) ->
- Dir = filename:join(AgentDir, DirName),
+ Dir = join(AgentDir, DirName),
{ok, Files} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ lists:foreach(fun(FName) -> file:delete(join(Dir, FName)) end,
Files),
delete_files(AgentDir, DirNames).
@@ -1481,8 +1478,8 @@ update_usm_mgr(Vsns, Dir) ->
end.
rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
+ ?line ok = file:rename(join(Dir,"usm.conf"),
+ join(Dir,"usm.old")),
Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero,
usmHMACSHAAuthProtocol, "", "",
usmDESPrivProtocol, "", "", "", ShaKey, DesKey},
@@ -1492,8 +1489,8 @@ rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
ok = snmp_config:write_agent_usm_config(Dir, "", Conf).
reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
+ ?line ok = file:rename(join(Dir,"usm.old"),
+ join(Dir,"usm.conf")).
update_community([v3], _Dir) ->
@@ -1526,7 +1523,7 @@ write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
rewrite_target_addr_conf(Dir, NewPort) ->
?DBG("rewrite_target_addr_conf -> entry with"
"~n NewPort: ~p", [NewPort]),
- TAFile = filename:join(Dir, "target_addr.conf"),
+ TAFile = join(Dir, "target_addr.conf"),
case file:read_file_info(TAFile) of
{ok, _} ->
ok;
@@ -1546,8 +1543,8 @@ rewrite_target_addr_conf(Dir, NewPort) ->
?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
+ ?line ok = file:rename(join(Dir,"target_addr.conf"),
+ join(Dir,"target_addr.old")),
?line ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs).
@@ -1565,8 +1562,8 @@ rewrite_target_addr_conf2(_NewPort,O) ->
O.
reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir, "target_addr.old"),
- filename:join(Dir, "target_addr.conf")).
+ ?line ok = file:rename(join(Dir, "target_addr.old"),
+ join(Dir, "target_addr.conf")).
write_target_params_conf(Dir, Vsns) ->
F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv};
@@ -1578,14 +1575,14 @@ write_target_params_conf(Dir, Vsns) ->
rewrite_target_params_conf(Dir, SecName, SecLevel)
when is_list(SecName) andalso is_atom(SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
+ ?line ok = file:rename(join(Dir,"target_params.conf"),
+ join(Dir,"target_params.old")),
Conf = [{"target_v3", v3, usm, SecName, SecLevel}],
snmp_config:write_agent_target_params_config(Dir, "", Conf).
reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
+ ?line ok = file:rename(join(Dir,"target_params.old"),
+ join(Dir,"target_params.conf")).
write_notify_conf(Dir) ->
Conf = [{"standard trap", "std_trap", trap},
@@ -1648,6 +1645,9 @@ rpc(Node, F, A) ->
rpc:call(Node, snmpa, F, A).
+join(Dir, File) ->
+ filename:join(Dir, File).
+
%% await_pdu(To) ->
%% await_response(To, pdu).
%%
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.
%%
%% ---