%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(os_mon_mib_SUITE).
%%-----------------------------------------------------------------
%% This suite can no longer be executed standalone, i.e. it must be
%% executed with common test. The reason is that ct_snmp is used
%% instead of the snmp application directly. The suite requires a
%% config file, os_mon_mib_SUITE.cfg, found in the same directory as
%% the suite.
%%
%% Execute with:
%% > ct_run -suite os_mon_mib_SUITE -config os_mon_mib_SUITE.cfg
%%-----------------------------------------------------------------
-include_lib("common_test/include/ct.hrl").
-include_lib("os_mon/include/OTP-OS-MON-MIB.hrl").
-include_lib("snmp/include/snmp_types.hrl").
% Test server specific exports
-export([all/0, suite/0, groups/0,
init_per_suite/1, end_per_suite/1]).
% Test cases must be exported.
-export([update_load_table/1]).
-export([get_mem_sys_mark/1, get_mem_proc_mark/1, get_disk_threshold/1,
get_load_table/1, get_disk_table/1,
real_snmp_request/1, load_unload/1]).
-export([sys_tot_mem/1, sys_used_mem/1, large_erl_process/1,
large_erl_process_mem/1, cpu_load/1, cpu_load5/1, cpu_load15/1,
os_wordsize/1, sys_tot_mem64/1, sys_used_mem64/1,
large_erl_process_mem64/1, disk_descr/1, disk_kbytes/1,
disk_capacity/1]).
-export([otp_6351/1, otp_7441/1]).
-define(TRAP_UDP, 5000).
-define(AGENT_UDP, 4000).
-define(CONF_FILE_VER, [v2]).
-define(SYS_NAME, "Test os_mon_mibs").
-define(MAX_MSG_SIZE, 484).
-define(ENGINE_ID, "mgrEngine").
-define(MGR_PORT, 5001).
%%---------------------------------------------------------------------
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,6}},
{require, snmp_mgr_agent, snmp}].
all() ->
[load_unload, get_mem_sys_mark, get_mem_proc_mark,
get_disk_threshold, get_load_table,
{group, get_next_load_table}, get_disk_table,
{group, get_next_disk_table}, real_snmp_request,
update_load_table, {group, tickets}].
groups() ->
[{tickets, [], [otp_6351, otp_7441]},
{get_next_load_table, [],
[sys_tot_mem, sys_used_mem, large_erl_process,
large_erl_process_mem, cpu_load, cpu_load5, cpu_load15,
os_wordsize, sys_tot_mem64, sys_used_mem64,
large_erl_process_mem64]},
{get_next_disk_table, [],
[disk_descr, disk_kbytes, disk_capacity]}].
%%---------------------------------------------------------------------
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%% Description: Initiation before the whole suite
%%
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
application:start(sasl),
application:start(mnesia),
application:start(os_mon),
ok = ct_snmp:start(Config,snmp_mgr_agent),
%% Load the mibs that should be tested
otp_mib:load(snmp_master_agent),
os_mon_mib:load(snmp_master_agent),
Config.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
ConfDir = filename:join(PrivDir,"conf"),
DbDir = filename:join(PrivDir,"db"),
MgrDir = filename:join(PrivDir, "mgr"),
%% Uload mibs
snmpa:unload_mibs(snmp_master_agent,["OTP-OS-MON-MIB"]),
otp_mib:unload(snmp_master_agent),
%% Clean up
application:stop(snmp),
application:stop(mnesia),
application:stop(os_mon),
del_dir(ConfDir),
del_dir(DbDir),
(catch del_dir(MgrDir)),
ok.
%%---------------------------------------------------------------------
%% Test cases
%%---------------------------------------------------------------------
%% Test to unload and the reload the OTP.mib
load_unload(Config) when is_list(Config) ->
os_mon_mib:unload(snmp_master_agent),
os_mon_mib:load(snmp_master_agent),
ok.
%%---------------------------------------------------------------------
%% check os_mon_mib:update_load_table error handling
update_load_table(Config) when is_list(Config) ->
Node = start_node(),
ok = rpc:call(Node,application,start,[sasl]),
ok = rpc:call(Node,application,start,[os_mon]),
ok = os_mon_mib:update_load_table(),
rpc:call(Node,application,stop,[os_mon]),
ok = os_mon_mib:update_load_table(),
stop_node(Node),
ok.
%% like update_load_table, when memsup_system_only==true
otp_6351(Config) when is_list(Config) ->
Node = start_node(),
ok = rpc:call(Node,application,start,[sasl]),
ok = rpc:call(Node,application,load,[os_mon]),
ok = rpc:call(Node,application,set_env,
[os_mon,memsup_system_only,true]),
ok = rpc:call(Node,application,start,[os_mon]),
Res = rpc:call(Node,os_mon_mib,get_load,[Node]),
if
is_tuple(Res), element(1, Res)==loadTable ->
ok;
true ->
ct:fail(Res)
end,
rpc:call(Node,application,stop,[os_mon]),
stop_node(Node),
ok.
%%---------------------------------------------------------------------
%% Simulates a get call to test the instrumentation function
%% for the loadMemorySystemWatermark variable.
get_mem_sys_mark(Config) when is_list(Config) ->
case os_mon_mib:mem_sys_mark(get) of
{value, SysMark} when is_integer(SysMark) ->
ok;
_ ->
ct:fail(sys_mark_value_not_integer)
end.
%%---------------------------------------------------------------------
%% Simulates a get call to test the instrumentation function
%% for the loadMemoryErlProcWatermark variable.
get_mem_proc_mark(Config) when is_list(Config) ->
case os_mon_mib:mem_proc_mark(get) of
{value, ProcMark} when is_integer(ProcMark) ->
ok;
_ ->
ct:fail(proc_mark_value_not_integer)
end.
%%---------------------------------------------------------------------
%% Simulates a get call to test the instrumentation function
%% for the diskAlmostFullThreshold variable.
get_disk_threshold(Config) when is_list(Config) ->
case os_mon_mib:disk_threshold(get) of
{value, ProcMark} when is_integer(ProcMark) ->
ok;
_ ->
ct:fail(disk_threshold_value_not_integer)
end.
%%---------------------------------------------------------------------
%%% Note that when we have a string key, as in loadTable, the
%%% instrumentation will deal with the [length(String), String]. We
%%% have to know about this, when short cutting SNMP and calling
%%% instrumentation functions directly as done in most test cases in
%%% this test suite
%% Simulates get calls to test the instrumentation function
%% for the loadTable
get_load_table(Config) when is_list(Config) ->
NodeStr = atom_to_list(node()),
NodeLen = length(NodeStr),
{_, _, {Pid, _}} = memsup:get_memory_data(),
PidStr = lists:flatten(io_lib:format("~w", [Pid])),
[{value, NodeStr},{value, PidStr}] =
os_mon_mib:load_table(get, [NodeLen | NodeStr],
[?loadErlNodeName, ?loadLargestErlProcess]),
Values = os_mon_mib:load_table(get, [NodeLen | NodeStr] ,
[?loadSystemTotalMemory,
?loadSystemUsedMemory,
?loadLargestErlProcessUsedMemory,
?loadCpuLoad,
?loadCpuLoad5,
?loadCpuLoad15,
?loadOsWordsize,
?loadSystemTotalMemory64,
?loadSystemUsedMemory64,
?loadLargestErlProcessUsedMemory64]),
IsInt = fun({value, Val}) when is_integer(Val) ->
true;
(_) ->
false
end,
NewValues = lists:filter(IsInt, Values),
case length(NewValues) of
10 ->
ok;
_ ->
ct:fail(value_not_integer)
end,
[{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance}] =
os_mon_mib:load_table(get, [3, 102, 111, 111],
[?loadErlNodeName,
?loadSystemTotalMemory,
?loadSystemUsedMemory,
?loadLargestErlProcess,
?loadLargestErlProcessUsedMemory,
?loadCpuLoad,
?loadCpuLoad5,
?loadCpuLoad15,
?loadOsWordsize,
?loadSystemTotalMemory64,
?loadSystemUsedMemory64,
?loadLargestErlProcessUsedMemory64]),
ok.
%%---------------------------------------------------------------------
sys_tot_mem(Config) when is_list(Config) ->
[{[?loadSystemTotalMemory, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(sys_tot_mem_value_not_integer)
end.
sys_used_mem(Config) when is_list(Config) ->
[{[?loadSystemUsedMemory, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(sys_used_mem_value_not_integer)
end.
large_erl_process(Config) when is_list(Config) ->
{_, _, {Pid, _}} = memsup:get_memory_data(),
PidStr = lists:flatten(io_lib:format("~w", [Pid])),
[{[?loadLargestErlProcess, Len | NodeStr], PidStr}] =
os_mon_mib:load_table(get_next,[], [?loadLargestErlProcess]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
ok.
large_erl_process_mem(Config) when is_list(Config) ->
[{[?loadLargestErlProcessUsedMemory, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next,[],
[?loadLargestErlProcessUsedMemory]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(erl_pid_mem_value_not_integer)
end.
cpu_load(Config) when is_list(Config) ->
[{[?loadCpuLoad, Len | NodeStr], Load}] =
os_mon_mib:load_table(get_next,[], [?loadCpuLoad]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Load of
Load when is_integer(Load) ->
ok;
_ ->
ct:fail(cpu_load_value_not_integer)
end.
cpu_load5(Config) when is_list(Config) ->
[{[?loadCpuLoad5, Len | NodeStr], Load}] =
os_mon_mib:load_table(get_next,[], [?loadCpuLoad5]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Load of
Load when is_integer(Load) ->
ok;
_ ->
ct:fail(cpu_load5_value_not_integer)
end.
cpu_load15(Config) when is_list(Config) ->
[{[?loadCpuLoad15, Len | NodeStr], Load}] =
os_mon_mib:load_table(get_next,[], [?loadCpuLoad15]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Load of
Load when is_integer(Load) ->
ok;
_ ->
ct:fail(cpu_load15_value_not_integer)
end.
os_wordsize(Config) when is_list(Config) ->
[{[?loadOsWordsize, Len | NodeStr], Wordsize}] =
os_mon_mib:load_table(get_next,[], [?loadOsWordsize]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Wordsize of
Wordsize when is_integer(Wordsize) ->
ok;
_ ->
ct:fail(os_wordsize_value_not_integer)
end.
sys_tot_mem64(Config) when is_list(Config) ->
[{[?loadSystemTotalMemory64, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory64]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(sys_tot_mem_value_not_integer)
end.
sys_used_mem64(Config) when is_list(Config) ->
[{[?loadSystemUsedMemory64, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory64]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(sys_used_mem_value_not_integer)
end.
large_erl_process_mem64(Config) when is_list(Config) ->
[{[?loadLargestErlProcessUsedMemory64, Len | NodeStr], Mem}] =
os_mon_mib:load_table(get_next,[],
[?loadLargestErlProcessUsedMemory64]),
Len = length(NodeStr),
true = lists:member(list_to_atom(NodeStr), [node() | nodes()]),
case Mem of
Mem when is_integer(Mem) ->
ok;
_ ->
ct:fail(erl_pid_mem_value_not_integer)
end.
%%---------------------------------------------------------------------
%% Simulates get calls to test the instrumentation function
%% for the diskTable.
get_disk_table(Config) when is_list(Config) ->
DiskData = disksup:get_disk_data(),
DiskDataLen = length(DiskData),
if
DiskDataLen > 0 ->
[{value, Value}] =
os_mon_mib:disk_table(get, [1,1], [?diskDescr]),
case is_list(Value) of
true ->
ok;
false ->
ct:fail(value_not_a_string)
end,
Values = os_mon_mib:disk_table(get, [1,1],
[?diskId,
?diskKBytes,
?diskCapacity]),
IsInt = fun({value, Val}) when is_integer(Val) ->
true;
(_) ->
false
end,
NewValues = lists:filter(IsInt, Values),
case length(NewValues) of
3 ->
ok;
_ ->
ct:fail(value_not_integer)
end
end,
[{noValue,noSuchInstance}, {noValue,noSuchInstance},
{noValue,noSuchInstance}, {noValue,noSuchInstance}] =
os_mon_mib:disk_table(get, [1, DiskDataLen + 1], [?diskId,
?diskDescr,
?diskKBytes,
?diskCapacity]),
ok.
%%---------------------------------------------------------------------
disk_descr(Config) when is_list(Config) ->
[{[?diskDescr, 1,1], Descr}] =
os_mon_mib:disk_table(get_next, [], [?diskDescr]),
case Descr of
Descr when is_list(Descr) ->
ok;
_ ->
ct:fail(disk_descr_value_not_a_string)
end.
disk_kbytes(Config) when is_list(Config) ->
[{[?diskKBytes, 1,1], Kbytes}] =
os_mon_mib:disk_table(get_next,[], [?diskKBytes]),
case Kbytes of
Kbytes when is_integer(Kbytes) ->
ok;
_ ->
ct:fail(disk_kbytes_value_not_integer)
end.
disk_capacity(Config) when is_list(Config) ->
[{[?diskCapacity, 1,1], Capacity}] =
os_mon_mib:disk_table(get_next,[], [?diskCapacity]),
case Capacity of
Capacity when is_integer(Capacity) ->
ok;
_ ->
ct:fail(disk_capacity_value_not_integer)
end.
%%---------------------------------------------------------------------
%% Starts an snmp manager and sends a real snmp-request. i.e.
%% sends a udp message on the correct format.
real_snmp_request(Config) when is_list(Config) ->
NodStr = atom_to_list(node()),
Len = length(NodStr),
{_, _, {Pid, _}} = memsup:get_memory_data(),
PidStr = lists:flatten(io_lib:format("~w", [Pid])),
io:format("FOO: ~p~n", [PidStr]),
ok = snmp_get([?loadEntry ++
[?loadLargestErlProcess, Len | NodStr]],
PidStr),
ok = snmp_get_next([?loadEntry ++
[?loadSystemUsedMemory, Len | NodStr]],
?loadEntry ++ [?loadSystemUsedMemory + 1, Len
| NodStr], PidStr),
ok = snmp_set([?loadEntry ++ [?loadLargestErlProcess, Len | NodStr]],
s, "<0.101.0>", Config),
ok.
%% Starts an snmp manager and requests total memory. Was previously
%% integer32 which was errornous on 64 bit machines.
otp_7441(Config) when is_list(Config) ->
NodStr = atom_to_list(node()),
Len = length(NodStr),
Oids = [Oid|_] = [?loadEntry ++ [?loadSystemTotalMemory, Len | NodStr]],
{noError,0,[#varbind{oid = Oid, variabletype = 'Unsigned32'}]} =
ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent),
ok.
%%---------------------------------------------------------------------
%% Internal functions
%%---------------------------------------------------------------------
start_node() ->
Pa = filename:dirname(code:which(?MODULE)),
{ok,Node} = test_server:start_node(testnisse, slave, [{args, " -pa " ++ Pa}]),
Node.
stop_node(Node) ->
test_server:stop_node(Node).
del_dir(Dir) ->
io:format("Deleting: ~s~n",[Dir]),
{ok, Files} = file:list_dir(Dir),
FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end,
Files),
lists:foreach(fun file:delete/1, FullPathFiles),
file:del_dir(Dir).
%%---------------------------------------------------------------------
snmp_get(Oids = [Oid |_], Result) ->
{noError,0,[#varbind{oid = Oid,
variabletype = 'OCTET STRING',
value = Result}]} =
ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent),
ok.
snmp_get_next(Oids, NextOid, Result) ->
{noError,0,[#varbind{oid = NextOid,
variabletype = 'OCTET STRING',
value = Result}]} =
ct_snmp:get_next_values(os_mon_mib_test, Oids, snmp_mgr_agent),
ok.
snmp_set(Oid, ValuType, Value, Config) ->
{notWritable, _, _} =
ct_snmp:set_values(os_mon_mib_test, [{Oid, ValuType, Value}],
snmp_mgr_agent, Config),
ok.