1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(os_mon).
21
22-behaviour(application).
23-behaviour(supervisor).
24
25%% API
26-export([call/2, call/3, get_env/2, open_port/2]).
27
28%% Application callbacks
29-export([start/2, stop/1]).
30
31%% Supervisor callbacks
32-export([init/1]).
33
34%%%-----------------------------------------------------------------
35%%% API
36%%%-----------------------------------------------------------------
37
38call(Service, Request) ->
39    call(Service, Request, 5000).
40
41call(Service, Request, Timeout) ->
42    try gen_server:call(server_name(Service), Request, Timeout)
43    catch
44	exit:{noproc, Call} ->
45	    case lists:keysearch(os_mon, 1,
46				 application:which_applications()) of
47		{value, _AppInfo} ->
48		    case startp(Service) of
49			true ->
50			    erlang:exit({noproc, Call});
51			false ->
52			    String = "OS_MON (~p) called by ~p, "
53				     "unavailable~n",
54			    error_logger:warning_msg(String,
55						     [Service, self()]),
56			    Service:dummy_reply(Request)
57		    end;
58		false ->
59		    String = "OS_MON (~p) called by ~p, not started~n",
60		    error_logger:warning_msg(String, [Service, self()]),
61		    Service:dummy_reply(Request)
62	    end
63    end.
64
65get_env(Service, Param) ->
66    case application:get_env(os_mon, Param) of
67	{ok, Value} ->
68	    case Service:param_type(Param, Value) of
69		true ->
70		    Value;
71		false ->
72		    String = "OS_MON (~p), ignoring "
73			     "bad configuration parameter (~p=~p)~n"
74	                     "Using default value instead~n",
75		    error_logger:warning_msg(String,
76					     [Service, Param, Value]),
77		    Service:param_default(Param)
78	    end;
79	undefined ->
80	    Service:param_default(Param)
81    end.
82
83open_port(Name, Opts) ->
84    PrivDir = code:priv_dir(os_mon),
85    ReleasedPath = filename:join([PrivDir,"bin",Name]),
86    %% Check os_mon*/priv/bin/Name
87    case filelib:is_regular(ReleasedPath) of
88	true ->
89	    erlang:open_port({spawn, "\""++ReleasedPath++"\""}, Opts);
90	false ->
91	    %% Use os_mon*/priv/bin/Arch/Name
92	    ArchPath =
93		filename:join(
94		  [PrivDir,"bin",erlang:system_info(system_architecture),Name]),
95	    erlang:open_port({spawn, "\""++ArchPath++"\""}, Opts)
96    end.
97
98
99%%%-----------------------------------------------------------------
100%%% Application callbacks
101%%%-----------------------------------------------------------------
102
103start(_, _) ->
104    supervisor:start_link({local, os_mon_sup}, os_mon, []).
105
106stop(_) ->
107    ok.
108
109%%%-----------------------------------------------------------------
110%%% Supervisor callbacks
111%%%-----------------------------------------------------------------
112
113init([]) ->
114    SupFlags = case os:type() of
115		   {win32, _} ->
116		       {one_for_one, 5, 3600};
117		   _ ->
118		       {one_for_one, 4, 3600}
119	       end,
120    SysInf = childspec(sysinfo, startp(sysinfo)),
121    DskSup = childspec(disksup, startp(disksup)),
122    MemSup = childspec(memsup,  startp(memsup)),
123    CpuSup = childspec(cpu_sup, startp(cpu_sup)),
124    OsSup  = childspec(os_sup,  startp(os_sup)),
125    {ok, {SupFlags, SysInf ++ DskSup ++ MemSup ++ CpuSup ++ OsSup}}.
126
127childspec(_Service, false) ->
128    [];
129childspec(cpu_sup, true) ->
130    [{cpu_sup, {cpu_sup, start_link, []},
131      permanent, 2000, worker, [cpu_sup]}];
132childspec(disksup, true) ->
133    [{disksup, {disksup, start_link, []},
134      permanent, 2000, worker, [disksup]}];
135childspec(memsup, true) ->
136    [{memsup, {memsup, start_link, []},
137      permanent, 2000, worker, [memsup]}];
138childspec(os_sup, true) ->
139    OS = os:type(),
140    Mod = case OS of
141	      {win32, _} -> nteventlog; % windows
142	      _ -> os_sup % solaris
143	  end,
144    [{os_sup, {os_sup, start_link, [OS]},
145      permanent, 10000, worker, [Mod]}];
146childspec(sysinfo, true) ->
147    [{os_mon_sysinfo, {os_mon_sysinfo, start_link, []},
148      permanent, 2000, worker, [os_mon_sysinfo]}].
149
150%%%-----------------------------------------------------------------
151%%% Internal functions (OS_Mon configuration)
152%%%-----------------------------------------------------------------
153
154startp(Service) ->
155    %% Available for this platform?
156    case lists:member(Service, services(os:type())) of
157	true ->
158	    %% Is there a start configuration parameter?
159	    case start_param(Service) of
160		none ->
161		    true;
162		Param ->
163		    %% Is the start configuration parameter 'true'?
164		    case application:get_env(os_mon, Param) of
165			{ok, true} ->
166			    true;
167			_ ->
168			    false
169		    end
170	    end;
171	false ->
172	    false
173    end.
174
175services({unix, sunos}) ->
176    [cpu_sup, disksup, memsup, os_sup];
177services({unix, _}) -> % Other unix.
178    [cpu_sup, disksup, memsup];
179services({win32, _}) ->
180    [disksup, memsup, os_sup, sysinfo].
181
182server_name(cpu_sup) -> cpu_sup;
183server_name(disksup) -> disksup;
184server_name(memsup) ->  memsup;
185server_name(os_sup) ->  os_sup_server;
186server_name(sysinfo) -> os_mon_sysinfo.
187
188start_param(cpu_sup) -> start_cpu_sup;
189start_param(disksup) -> start_disksup;
190start_param(memsup) ->  start_memsup;
191start_param(os_sup) ->  start_os_sup;
192start_param(sysinfo) -> none.
193