fix(license): print warning at start

This commit is contained in:
Zaiming (Stone) Shi 2022-04-22 17:31:20 +02:00
parent 123e456287
commit 1c74c83f5e
6 changed files with 74 additions and 63 deletions

View File

@ -322,7 +322,8 @@ delete_old_file(_New, Old) ->
case is_generated_file(Old) andalso filelib:is_regular(Old) andalso file:delete(Old) of case is_generated_file(Old) andalso filelib:is_regular(Old) andalso file:delete(Old) of
ok -> ok ->
ok; ok;
false -> %% the file is not generated by us, or it is already deleted %% the file is not generated by us, or it is already deleted
false ->
ok; ok;
{error, Reason} -> {error, Reason} ->
?SLOG(error, #{msg => "failed_to_delete_ssl_file", file_path => Old, reason => Reason}) ?SLOG(error, #{msg => "failed_to_delete_ssl_file", file_path => Old, reason => Reason})
@ -412,16 +413,21 @@ pem_dir(Dir) ->
filename:join([emqx:mutable_certs_dir(), Dir]). filename:join([emqx:mutable_certs_dir(), Dir]).
is_hex_str(HexStr) -> is_hex_str(HexStr) ->
try is_hex_str2(ensure_str(HexStr)) try
catch throw: not_hex -> false is_hex_str2(ensure_str(HexStr))
catch
throw:not_hex -> false
end. end.
is_hex_str2(HexStr) -> is_hex_str2(HexStr) ->
_ = [case S of _ = [
case S of
S when S >= $0, S =< $9 -> S; S when S >= $0, S =< $9 -> S;
S when S >= $a, S =< $f -> S; S when S >= $a, S =< $f -> S;
_ -> throw(not_hex) _ -> throw(not_hex)
end || S <- HexStr], end
|| S <- HexStr
],
true. true.
hex_str(Bin) -> hex_str(Bin) ->
@ -457,8 +463,7 @@ do_drop_invalid_certs([Key | Keys], SSL) ->
PemOrPath -> PemOrPath ->
case is_pem(PemOrPath) orelse is_valid_pem_file(PemOrPath) of case is_pem(PemOrPath) orelse is_valid_pem_file(PemOrPath) of
true -> do_drop_invalid_certs(Keys, SSL); true -> do_drop_invalid_certs(Keys, SSL);
{error, _} -> {error, _} -> do_drop_invalid_certs(Keys, maps:without([Key], SSL))
do_drop_invalid_certs(Keys, maps:without([Key], SSL))
end end
end. end.

View File

@ -488,7 +488,8 @@ is_tcp_server_available(Host, Port, Timeout) ->
start_ekka() -> start_ekka() ->
try mnesia_hook:module_info() of try mnesia_hook:module_info() of
_ -> ekka:start() _ -> ekka:start()
catch _:_ -> catch
_:_ ->
%% Falling back to using Mnesia DB backend. %% Falling back to using Mnesia DB backend.
application:set_env(mria, db_backend, mnesia), application:set_env(mria, db_backend, mnesia),
ekka:start() ekka:start()

View File

@ -223,7 +223,9 @@ t_callback_crash(_Config) ->
Opts = #{rawconf_with_defaults => true}, Opts = #{rawconf_with_defaults => true},
ok = emqx_config_handler:add_handler(CrashPath, ?MODULE), ok = emqx_config_handler:add_handler(CrashPath, ?MODULE),
Old = emqx:get_raw_config(CrashPath), Old = emqx:get_raw_config(CrashPath),
?assertMatch({error, {config_update_crashed, _}}, emqx:update_config(CrashPath, <<"89%">>, Opts)), ?assertMatch(
{error, {config_update_crashed, _}}, emqx:update_config(CrashPath, <<"89%">>, Opts)
),
New = emqx:get_raw_config(CrashPath), New = emqx:get_raw_config(CrashPath),
?assertEqual(Old, New), ?assertEqual(Old, New),
ok = emqx_config_handler:remove_handler(CrashPath), ok = emqx_config_handler:remove_handler(CrashPath),

View File

@ -9,20 +9,20 @@
-define(EVALUATION_LOG, -define(EVALUATION_LOG,
"\n" "\n"
"================================================================================\n" "========================================================================\n"
"This is an evaluation license that is restricted to 1000 concurrent connections.\n" "Using an evaluation license limited to ~p concurrent connections.\n"
"If you already have a paid license, please apply it now.\n" "Apply a license at https://emqx.com/apply-licenses/emqx.\n"
"Or you could visit https://emqx.com/apply-licenses/emqx to get a trial license.\n" "Or contact EMQ customer services.\n"
"================================================================================\n" "========================================================================\n"
). ).
-define(EXPIRY_LOG, -define(EXPIRY_LOG,
"\n" "\n"
"======================================================\n" "========================================================================\n"
"Your license has expired.\n" "License has been expired for ~p days.\n"
"Please visit https://emqx.com/apply-licenses/emqx or\n" "Apply a new license at https://emqx.com/apply-licenses/emqx.\n"
"contact customer services.\n" "Or contact EMQ customer services.\n"
"======================================================\n" "========================================================================\n"
). ).
-define(OFFICIAL, 1). -define(OFFICIAL, 1).

View File

@ -11,6 +11,7 @@
-define(CHECK_INTERVAL, 5000). -define(CHECK_INTERVAL, 5000).
-define(EXPIRY_ALARM_CHECK_INTERVAL, 24 * 60 * 60). -define(EXPIRY_ALARM_CHECK_INTERVAL, 24 * 60 * 60).
-define(OK(EXPR), try _ = begin EXPR end, ok catch _:_ -> ok end).
-export([ -export([
start_link/1, start_link/1,
@ -18,7 +19,8 @@
update/1, update/1,
dump/0, dump/0,
purge/0, purge/0,
limits/0 limits/0,
print_warnings/1
]). ]).
%% gen_server callbacks %% gen_server callbacks
@ -78,7 +80,7 @@ init([LicenseFetcher, CheckInterval]) ->
?LICENSE_TAB = ets:new(?LICENSE_TAB, [ ?LICENSE_TAB = ets:new(?LICENSE_TAB, [
set, protected, named_table, {read_concurrency, true} set, protected, named_table, {read_concurrency, true}
]), ]),
#{} = check_license(License), ok = print_warnings(check_license(License)),
State0 = ensure_check_license_timer(#{ State0 = ensure_check_license_timer(#{
check_license_interval => CheckInterval, check_license_interval => CheckInterval,
license => License license => License
@ -90,7 +92,7 @@ init([LicenseFetcher, CheckInterval]) ->
end. end.
handle_call({update, License}, _From, State) -> handle_call({update, License}, _From, State) ->
_ = expiry_early_alarm(License), ok = expiry_early_alarm(License),
{reply, check_license(License), State#{license => License}}; {reply, check_license(License), State#{license => License}};
handle_call(dump, _From, #{license := License} = State) -> handle_call(dump, _From, #{license := License} = State) ->
{reply, emqx_license_parser:dump(License), State}; {reply, emqx_license_parser:dump(License), State};
@ -109,7 +111,7 @@ handle_info(check_license, #{license := License} = State) ->
?tp(debug, emqx_license_checked, #{}), ?tp(debug, emqx_license_checked, #{}),
{noreply, NewState}; {noreply, NewState};
handle_info(check_expiry_alarm, #{license := License} = State) -> handle_info(check_expiry_alarm, #{license := License} = State) ->
_ = expiry_early_alarm(License), ok = expiry_early_alarm(License),
NewState = ensure_check_expiry_timer(State), NewState = ensure_check_expiry_timer(State),
{noreply, NewState}; {noreply, NewState};
handle_info(_Msg, State) -> handle_info(_Msg, State) ->
@ -138,21 +140,21 @@ cancel_timer(State, Key) ->
check_license(License) -> check_license(License) ->
DaysLeft = days_left(License), DaysLeft = days_left(License),
NeedRestrict = need_restrict(License, DaysLeft), IsOverdue = is_overdue(License, DaysLeft),
Limits = limits(License, NeedRestrict), NeedRestriction = IsOverdue,
MaxConn = emqx_license_parser:max_connections(License),
Limits = limits(License, NeedRestriction),
true = apply_limits(Limits), true = apply_limits(Limits),
#{ #{
warn_evaluation => warn_evaluation(License, NeedRestrict), warn_evaluation => warn_evaluation(License, NeedRestriction, MaxConn),
warn_expiry => warn_expiry(License, NeedRestrict) warn_expiry => {(DaysLeft < 0), -DaysLeft}
}. }.
warn_evaluation(License, false) -> warn_evaluation(License, false, MaxConn) ->
emqx_license_parser:customer_type(License) == ?EVALUATION_CUSTOMER; {emqx_license_parser:customer_type(License) == ?EVALUATION_CUSTOMER, MaxConn};
warn_evaluation(_License, _NeedRestrict) -> warn_evaluation(_License, _NeedRestrict, _Limits) ->
false. false.
warn_expiry(_License, NeedRestrict) -> NeedRestrict.
limits(License, false) -> #{max_connections => emqx_license_parser:max_connections(License)}; limits(License, false) -> #{max_connections => emqx_license_parser:max_connections(License)};
limits(_License, true) -> #{max_connections => ?ERR_EXPIRED}. limits(_License, true) -> #{max_connections => ?ERR_EXPIRED}.
@ -161,19 +163,20 @@ days_left(License) ->
{DateNow, _} = calendar:universal_time(), {DateNow, _} = calendar:universal_time(),
calendar:date_to_gregorian_days(DateEnd) - calendar:date_to_gregorian_days(DateNow). calendar:date_to_gregorian_days(DateEnd) - calendar:date_to_gregorian_days(DateNow).
need_restrict(License, DaysLeft) -> is_overdue(License, DaysLeft) ->
CType = emqx_license_parser:customer_type(License), CType = emqx_license_parser:customer_type(License),
Type = emqx_license_parser:license_type(License), Type = emqx_license_parser:license_type(License),
DaysLeft < 0 andalso small_customer_overdue(CType, DaysLeft) orelse
(Type =/= ?OFFICIAL) orelse small_customer_over_expired(CType, DaysLeft). non_official_license_overdue(Type, DaysLeft).
small_customer_over_expired(?SMALL_CUSTOMER, DaysLeft) when %% small customers overdue 90 days after license expiry date
DaysLeft < ?EXPIRED_DAY small_customer_overdue(?SMALL_CUSTOMER, DaysLeft) -> DaysLeft < ?EXPIRED_DAY;
-> small_customer_overdue(_CType, _DaysLeft) -> false.
true;
small_customer_over_expired(_CType, _DaysLeft) -> %% never restrict official license
false. non_official_license_overdue(?OFFICIAL, _) -> false;
non_official_license_overdue(_, DaysLeft) -> DaysLeft < 0.
apply_limits(Limits) -> apply_limits(Limits) ->
ets:insert(?LICENSE_TAB, {limits, Limits}). ets:insert(?LICENSE_TAB, {limits, Limits}).
@ -181,8 +184,23 @@ apply_limits(Limits) ->
expiry_early_alarm(License) -> expiry_early_alarm(License) ->
case days_left(License) < 30 of case days_left(License) < 30 of
true -> true ->
DateEnd = emqx_license_parser:expiry_date(License), {Y, M, D} = emqx_license_parser:expiry_date(License),
catch emqx_alarm:activate(license_expiry, #{expiry_at => DateEnd}); Date = iolist_to_binary(io_lib:format("~B~2..0B~2..0B", [Y, M, D])),
?OK(emqx_alarm:activate(license_expiry, #{expiry_at => Date}));
false -> false ->
catch emqx_alarm:deactivate(license_expiry) ?OK(emqx_alarm:deactivate(license_expiry))
end. end.
print_warnings(Warnings) ->
ok = print_evaluation_warning(Warnings),
ok = print_expiry_warning(Warnings).
print_evaluation_warning(#{warn_evaluation := {true, MaxConn}}) ->
io:format(?EVALUATION_LOG, [MaxConn]);
print_evaluation_warning(_) ->
ok.
print_expiry_warning(#{warn_expiry := {true, Days}}) ->
io:format(?EXPIRY_LOG, [Days]);
print_expiry_warning(_) ->
ok.

View File

@ -66,19 +66,4 @@ unload() ->
ok = emqx_ctl:unregister_command(license). ok = emqx_ctl:unregister_command(license).
print_warnings(Warnings) -> print_warnings(Warnings) ->
ok = print_evaluation_warning(Warnings), emqx_license_checker:print_warnings(Warnings).
ok = print_expiry_warning(Warnings).
%%------------------------------------------------------------------------------
%% Private functions
%%------------------------------------------------------------------------------
print_evaluation_warning(#{warn_evaluation := true}) ->
?PRINT_MSG(?EVALUATION_LOG);
print_evaluation_warning(_) ->
ok.
print_expiry_warning(#{warn_expiry := true}) ->
?PRINT_MSG(?EXPIRY_LOG);
print_expiry_warning(_) ->
ok.