mirror of
https://github.com/Telecominfraproject/wlan-cloud-loadsim.git
synced 2025-12-30 00:30:53 +00:00
369 lines
10 KiB
Erlang
369 lines
10 KiB
Erlang
%%%-------------------------------------------------------------------
|
|
%%% @author stephb
|
|
%%% @copyright (C) 2020, Arilia Wireless Inc.
|
|
%%% @doc
|
|
%%%
|
|
%%% @end
|
|
%%% Created : 15. Nov 2020 9:47 a.m.
|
|
%%%-------------------------------------------------------------------
|
|
-module(utils).
|
|
-author("stephb").
|
|
|
|
-include("../include/common.hrl").
|
|
|
|
%% API
|
|
-export([ make_dir/1,uuid/0,get_addr/0,get_addr2/0,app_name/0,app_name/1,priv_dir/0,app_env/2,to_string_list/2,to_binary_list/2,print_nodes_info/1,
|
|
do/2,pem_to_cert/1,pem_to_key/1,safe_binary/1,uuid_b/0,pem_key_is_encrypted/1,remove_pem_key_password/3,
|
|
noop/0,noop_mfa/0,split_into/2,select/3,adjust/2,apply_ntimes/4,
|
|
get_avg/1, new_avg/0,compute_avg/2,search_replace/3,json_node_info/1,
|
|
to_atom_list/2,to_atom_list/1,to_string_list/1,to_binary_list/1,
|
|
dump_data_in_file/2,identify/1,json_to_band/1,band_to_json/1,create_version/0,modify_mac/2]).
|
|
|
|
-type average() :: { CurrentValue::number(), HowManyValues::integer(), PastValues::[number()]}.
|
|
-export_type([average/0]).
|
|
|
|
-spec make_dir( DirName::string() ) -> ok | { error, atom() }.
|
|
make_dir(DirName)->
|
|
case file:make_dir(DirName) of
|
|
ok -> ok;
|
|
{error,eexist} -> ok;
|
|
Error -> Error
|
|
end.
|
|
|
|
-spec uuid()->string().
|
|
uuid()->
|
|
uuid:uuid_to_string(uuid:get_v4()).
|
|
|
|
-spec uuid_b()->binary().
|
|
uuid_b()->
|
|
list_to_binary(uuid:uuid_to_string(uuid:get_v4())).
|
|
|
|
-spec get_addr() -> IpAddress::string().
|
|
get_addr()->
|
|
{ok,Ifs} = inet:getifaddrs(),
|
|
case strip_ifs(Ifs) of
|
|
none -> "0.0.0.0";
|
|
[A|_] -> inet:ntoa(A)
|
|
end.
|
|
|
|
-spec get_addr2() -> IpAddress::string().
|
|
get_addr2()->
|
|
Node=atom_to_list(node()),
|
|
[_,Host]=string:tokens(Node,"@"),
|
|
case inet:gethostbyname(Host) of
|
|
{ok,{hostent,_Host2,_,inet,4,[Address1|_]}} ->
|
|
inet:ntoa(Address1);
|
|
Error->
|
|
Error
|
|
end.
|
|
|
|
-spec app_name( AppName::atom() )->ok.
|
|
app_name(AppName)->
|
|
persistent_term:put(running_app,AppName),
|
|
{ ok, RootDir } = file:get_cwd(),
|
|
PrivDir = filename:join([RootDir,"priv/"]),
|
|
persistent_term:put(priv_dir,PrivDir).
|
|
|
|
-spec app_name()->AppName::atom().
|
|
app_name()->
|
|
persistent_term:get(running_app).
|
|
|
|
-spec priv_dir()->DirName::string().
|
|
priv_dir()->
|
|
persistent_term:get(priv_dir).
|
|
|
|
-spec app_env(Key::atom(),Default::term())->Value::term().
|
|
app_env(Key,Default)->
|
|
application:get_env(app_name(),Key,Default).
|
|
|
|
|
|
print_nodes_info(Nodes)->
|
|
io:format("---------------------------------------------------------------------------------------------------------~n"),
|
|
io:format("|Node name | Total | Allocated | Biggest | Procs | Type |~n"),
|
|
io:format("---------------------------------------------------------------------------------------------------------~n"),
|
|
print_line(Nodes),
|
|
io:format("---------------------------------------------------------------------------------------------------------~n").
|
|
|
|
-spec json_node_info([{node(),atom()}])->binary().
|
|
json_node_info(Nodes)->
|
|
json_node_info(Nodes,[]).
|
|
|
|
json_node_info([],Acc)->
|
|
jiffy:encode(Acc);
|
|
json_node_info([{H,Type}|T],Acc)->
|
|
NodeInfo = node_info(H),
|
|
%% #{ total := Total , allocated := Allocated , worst := Worst , processes := Processes } = NodeInfo,
|
|
json_node_info(T,[NodeInfo#{ type => Type} |Acc]).
|
|
|
|
print_line([])->
|
|
ok;
|
|
print_line([{Node,Type}|T])->
|
|
NodeInfo = node_info(Node),
|
|
#{ total := Total , allocated := Allocated , worst := Worst , processes := Processes } = NodeInfo,
|
|
io:format("|~37s |~9.2f MB |~9.2f MB | ~9.2f MB | ~7b | ~10s|~n",[atom_to_list(Node),Total,Allocated,Worst,Processes,atom_to_list(Type)]),
|
|
print_line(T).
|
|
|
|
-spec node_info(Node::node())->#{ atom() => term()}.
|
|
node_info(Node)->
|
|
try
|
|
{Total,Allocated,{ _Pid, Worst}}=rpc:call(Node,memsup,get_memory_data,[]),
|
|
Processes = rpc:call(Node,cpu_sup,nprocs,[]),
|
|
#{ node => atom_to_binary(Node), total => Total/(1 bsl 20), allocated => Allocated/(1 bsl 20), worst => Worst/(1 bsl 20), processes => Processes }
|
|
catch
|
|
_:_ ->
|
|
#{ node => atom_to_binary(Node), total => 0, allocated => 0, worst => 0, processes => 0 }
|
|
end.
|
|
|
|
-spec apply_ntimes(Times::integer(),M::atom(),F::atom(),A::term())->[any()].
|
|
apply_ntimes(Times,M,F,A)->
|
|
apply_ntimes(Times,M,F,A,[]).
|
|
|
|
apply_ntimes(0,_,_,_,Acc)->
|
|
lists:reverse(Acc);
|
|
apply_ntimes(Times,M,F,A,Acc)->
|
|
R = apply(M,F,A),
|
|
apply_ntimes(Times-1,M,F,A,[R|Acc]).
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%% Local functions
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
strip_ifs(Ifs)->
|
|
strip_ifs(Ifs,[]).
|
|
|
|
strip_ifs([],[])->
|
|
none;
|
|
strip_ifs([],GoodAddresses)->
|
|
lists:reverse(GoodAddresses);
|
|
strip_ifs([{_IfName,Ifprops}|Tail],Addrs)->
|
|
Ifs=proplists:lookup_all(addr,Ifprops),
|
|
case Ifs of
|
|
[] ->
|
|
strip_ifs(Tail,Addrs);
|
|
Ifs ->
|
|
case good_address(Ifs) of
|
|
none ->
|
|
strip_ifs(Tail,Addrs);
|
|
Addr->
|
|
strip_ifs(Tail,[Addr|Addrs])
|
|
end
|
|
end.
|
|
|
|
good_address([])->
|
|
none;
|
|
good_address([{addr,{127,_,_,_}}|T]) ->
|
|
good_address(T);
|
|
good_address([{addr,{A,B,C,D}}|_Tail]) when A=/=127 ->
|
|
{A,B,C,D};
|
|
good_address([_|T])->
|
|
good_address(T).
|
|
|
|
to_string_list(L)->
|
|
to_string_list(L,[]).
|
|
to_atom_list(L)->
|
|
to_atom_list(L,[]).
|
|
to_binary_list(L)->
|
|
to_binary_list(L,[]).
|
|
|
|
-spec to_string_list([term()],[term()])->[string()].
|
|
to_string_list([],R)->
|
|
lists:reverse(R);
|
|
to_string_list([H|T],R) when is_list(H)->
|
|
to_string_list(T,[H|R]);
|
|
to_string_list([H|T],R) when is_atom(H)->
|
|
to_string_list(T,[atom_to_list(H)|R]);
|
|
to_string_list([H|T],R) when is_binary(H)->
|
|
to_string_list(T,[binary_to_list(H)|R]).
|
|
|
|
-spec to_binary_list([term()],[term()])->[string()].
|
|
to_binary_list([],R)->
|
|
lists:reverse(R);
|
|
to_binary_list([H|T],R) when is_list(H)->
|
|
to_binary_list(T,[list_to_binary(H)|R]);
|
|
to_binary_list([H|T],R) when is_atom(H)->
|
|
to_binary_list(T,[list_to_binary(atom_to_list(H))|R]);
|
|
to_binary_list([H|T],R) when is_binary(H)->
|
|
to_binary_list(T,[H|R]).
|
|
|
|
-spec to_atom_list([term()],[term()])->[string()].
|
|
to_atom_list([],R)->
|
|
lists:reverse(R);
|
|
to_atom_list([H|T],R) when is_list(H)->
|
|
to_atom_list(T,[list_to_atom(H)|R]);
|
|
to_atom_list([H|T],R) when is_atom(H)->
|
|
to_atom_list(T,[H|R]);
|
|
to_atom_list([H|T],R) when is_binary(H)->
|
|
to_atom_list(T,[binary_to_atom(H)|R]).
|
|
|
|
-spec do(boolean(),{atom(),atom(),term()})->ok.
|
|
do(true,{M,F,A})->
|
|
_=apply(M,F,A), ok;
|
|
do(false,_)->
|
|
ok.
|
|
|
|
pem_to_cert(FileName) when is_binary(FileName)->
|
|
pem_to_cert(binary_to_list(FileName));
|
|
pem_to_cert(FileName) when is_list(FileName)->
|
|
try
|
|
{ok,FileData}=file:read_file(FileName),
|
|
[{'Certificate',Cert,_}] = public_key:pem_decode(FileData),
|
|
{ ok , Cert }
|
|
catch
|
|
_:_ ->
|
|
{error,error_no_pem_file}
|
|
end.
|
|
|
|
pem_to_key(FileName) when is_binary(FileName)->
|
|
pem_to_key(binary_to_list(FileName));
|
|
pem_to_key(FileName) when is_list(FileName)->
|
|
try
|
|
{ok,FileData}=file:read_file(FileName),
|
|
[{T,K,_}]=public_key:pem_decode(FileData),
|
|
{ ok , {T,K}}
|
|
catch
|
|
_:_ ->
|
|
{error,error_no_pem_file}
|
|
end.
|
|
|
|
pem_key_is_encrypted(FileName) when is_binary(FileName)->
|
|
pem_to_key(binary_to_list(FileName));
|
|
pem_key_is_encrypted(FileName) when is_list(FileName)->
|
|
try
|
|
{ok,FileData}=file:read_file(FileName),
|
|
[{_,_,not_encrypted}]=public_key:pem_decode(FileData),
|
|
false
|
|
catch
|
|
_:_ ->
|
|
true
|
|
end.
|
|
|
|
-spec remove_pem_key_password(Password::string(),InFileName::string(),OutFileName::string()) -> boolean().
|
|
remove_pem_key_password(Password,InFileName,OutFilename)->
|
|
try
|
|
Cmd = io_lib:format("openssl rsa -passin pass:~s -in ~s -out ~s",[Password,InFileName,OutFilename]),
|
|
_Result = os:cmd(Cmd),
|
|
not pem_key_is_encrypted(OutFilename)
|
|
catch
|
|
_:_ ->
|
|
false
|
|
end.
|
|
|
|
-spec noop_mfa()->notification_cb().
|
|
noop_mfa()->
|
|
{utils,noop,[]}.
|
|
|
|
-spec noop()->ok.
|
|
noop()->
|
|
ok.
|
|
|
|
-spec safe_binary(binary()|string()|atom()|integer())->binary().
|
|
safe_binary(X) when is_binary(X)->
|
|
X;
|
|
safe_binary(X) when is_list(X)->
|
|
list_to_binary(X);
|
|
safe_binary(X) when is_atom(X)->
|
|
atom_to_binary(X);
|
|
safe_binary(X) when is_integer(X)->
|
|
integer_to_binary(X).
|
|
|
|
-spec split_into([term()],[term()])->[{term(),[term()]}].
|
|
split_into( A, B )->
|
|
LA = length(A),
|
|
LB = length(B),
|
|
Batch = LB div LA,
|
|
split_it(A,B,1,Batch,LB,[]).
|
|
|
|
split_it([H|T],B,Pos,Size,LB,Acc) when (Pos < LB) ->
|
|
SubList = lists:sublist(B,Pos,Size),
|
|
split_it(T,B,Pos+Size,Size,LB,[{H,SubList}|Acc]);
|
|
split_it(_,_,_,_,_,Acc)->
|
|
lists:reverse(Acc).
|
|
|
|
select(true,A,_B) ->A;
|
|
select(false,_A,B)->B.
|
|
|
|
-spec adjust(Max::integer(),Divisor::integer())->integer().
|
|
adjust(_Max,0)->
|
|
0;
|
|
adjust(Max,Divisor)->
|
|
min(Max, Max - ( Max rem Divisor)).
|
|
|
|
-spec new_avg()-> average().
|
|
new_avg()->
|
|
{0,10,[]}.
|
|
|
|
-spec compute_avg(number(),average())->average().
|
|
compute_avg(V,Avg)->
|
|
{_,L,Values}=Avg,
|
|
case length(Values) == L of
|
|
true ->
|
|
NV = [V|tl(Values)],
|
|
NewAverage = lists:sum(NV) / L,
|
|
{ NewAverage, L, NV };
|
|
false ->
|
|
NV = [V|Values],
|
|
NewAverage = lists:sum(NV) / length(NV),
|
|
{ NewAverage, L, NV }
|
|
end.
|
|
|
|
-spec get_avg(average())->number().
|
|
get_avg({V,_,_})->
|
|
V.
|
|
|
|
safe_list(I) when is_binary(I)->
|
|
binary_to_list(I);
|
|
safe_list(I) when is_list(I)->
|
|
I.
|
|
|
|
replace_data(Data,[])->
|
|
Data;
|
|
replace_data(Data,[{From,To}|T])->
|
|
NewData = string:replace(Data,From,To,all),
|
|
replace_data(NewData,T).
|
|
|
|
-spec search_replace(Infile::binary()|string(),OutFile::binary()|string(),[{From::string(),To::string()}]) -> ok.
|
|
search_replace(InFile,OutFile,Elements)->
|
|
{ ok , InData } = file:read_file(safe_list(InFile)),
|
|
NewData = replace_data(binary_to_list(InData),Elements),
|
|
file:write_file(safe_list(OutFile),list_to_binary(NewData)).
|
|
|
|
identify(D) when is_list(D) -> list;
|
|
identify(D) when is_binary(D) -> binary;
|
|
identify(D) when is_map(D) -> map;
|
|
identify(D) when is_integer(D) -> integer;
|
|
identify(_) -> unknown.
|
|
|
|
-spec dump_data_in_file(FileName::string(),Data::binary())->ok.
|
|
dump_data_in_file(FileName,Data)->
|
|
try
|
|
{ok,IoDev}=file:open(FileName,[append]),
|
|
io:fwrite(IoDev,"~s~n~n~n",[Data]),
|
|
_=file:close(IoDev),
|
|
ok
|
|
catch
|
|
_:_ -> ok
|
|
end.
|
|
|
|
-spec band_to_json(atom()) -> binary().
|
|
band_to_json('BAND2G') -> <<"2.4G">>;
|
|
band_to_json('BAND5G') -> <<"5G">>;
|
|
band_to_json('BAND5GL') -> <<"5GL">>;
|
|
band_to_json('BAND5GU') -> <<"5GU">>;
|
|
band_to_json(_) -> <<"2.4G">>.
|
|
|
|
-spec json_to_band(Band::binary())-> atom().
|
|
json_to_band(<<"2.4G">>) -> 'BAND2G';
|
|
json_to_band(<<"5G">>) -> 'BAND5G';
|
|
json_to_band(<<"5GL">>) -> 'BAND5GL';
|
|
json_to_band(<<"5GU">>) -> 'BAND5GU';
|
|
json_to_band(_) -> 'BAND2G'.
|
|
|
|
create_version()->
|
|
[<<"uuid">>,utils:uuid_b()].
|
|
|
|
modify_mac(MAC,N) ->
|
|
[X1,X2,$:,X3,X4,$:,X5,X6,$:,X7,X8,$:,X9,X10,$:,X11,_X12] = binary_to_list(MAC),
|
|
list_to_binary([X1,X2,$:,X3,X4,$:,X5,X6,$:,X7,X8,$:,X9,X10,$:,X11,N+$0]).
|
|
|
|
|
|
|