diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/rabbit.app.src | 3 | ||||
| -rw-r--r-- | src/rabbit_auth_backend_dummy.erl | 48 | ||||
| -rw-r--r-- | src/rabbit_auth_backend_internal.erl | 400 | ||||
| -rw-r--r-- | src/rabbit_cli.erl | 10 | ||||
| -rw-r--r-- | src/rabbit_control_main.erl | 114 | ||||
| -rw-r--r-- | src/rabbit_plugins_main.erl | 4 | ||||
| -rw-r--r-- | src/rabbit_types.erl | 168 |
7 files changed, 79 insertions, 668 deletions
diff --git a/src/rabbit.app.src b/src/rabbit.app.src index bb9cf2d124..572c1f6bc6 100644 --- a/src/rabbit.app.src +++ b/src/rabbit.app.src @@ -97,5 +97,6 @@ %% see rabbitmq-server#143 {credit_flow_default_credit, {200, 50}}, %% see rabbitmq-server#248 - {channel_operation_timeout, 5000} + %% and rabbitmq-server#667 + {channel_operation_timeout, 15000} ]}]}. diff --git a/src/rabbit_auth_backend_dummy.erl b/src/rabbit_auth_backend_dummy.erl deleted file mode 100644 index 0077b4c993..0000000000 --- a/src/rabbit_auth_backend_dummy.erl +++ /dev/null @@ -1,48 +0,0 @@ -%% The contents of this file are subject to the Mozilla Public License -%% Version 1.1 (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.mozilla.org/MPL/ -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and -%% limitations under the License. -%% -%% The Original Code is RabbitMQ. -%% -%% The Initial Developer of the Original Code is GoPivotal, Inc. -%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. -%% - --module(rabbit_auth_backend_dummy). --include("rabbit.hrl"). - --behaviour(rabbit_authn_backend). --behaviour(rabbit_authz_backend). - --export([user/0]). --export([user_login_authentication/2, user_login_authorization/1, - check_vhost_access/3, check_resource_access/3]). - --ifdef(use_specs). - --spec(user/0 :: () -> rabbit_types:user()). - --endif. - -%% A user to be used by the direct client when permission checks are -%% not needed. This user can do anything AMQPish. -user() -> #user{username = <<"none">>, - tags = [], - authz_backends = [{?MODULE, none}]}. - -%% Implementation of rabbit_auth_backend - -user_login_authentication(_, _) -> - {refused, "cannot log in conventionally as dummy user", []}. - -user_login_authorization(_) -> - {refused, "cannot log in conventionally as dummy user", []}. - -check_vhost_access(#auth_user{}, _VHostPath, _Sock) -> true. -check_resource_access(#auth_user{}, #resource{}, _Permission) -> true. diff --git a/src/rabbit_auth_backend_internal.erl b/src/rabbit_auth_backend_internal.erl deleted file mode 100644 index d7705d8e7b..0000000000 --- a/src/rabbit_auth_backend_internal.erl +++ /dev/null @@ -1,400 +0,0 @@ -%% The contents of this file are subject to the Mozilla Public License -%% Version 1.1 (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.mozilla.org/MPL/ -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and -%% limitations under the License. -%% -%% The Original Code is RabbitMQ. -%% -%% The Initial Developer of the Original Code is GoPivotal, Inc. -%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. -%% - --module(rabbit_auth_backend_internal). --include("rabbit.hrl"). - --behaviour(rabbit_authn_backend). --behaviour(rabbit_authz_backend). - --export([user_login_authentication/2, user_login_authorization/1, - check_vhost_access/3, check_resource_access/3]). - --export([add_user/2, delete_user/1, lookup_user/1, - change_password/2, clear_password/1, - hash_password/2, change_password_hash/2, change_password_hash/3, - set_tags/2, set_permissions/5, clear_permissions/2]). --export([user_info_keys/0, perms_info_keys/0, - user_perms_info_keys/0, vhost_perms_info_keys/0, - user_vhost_perms_info_keys/0, - list_users/0, list_users/2, list_permissions/0, - list_user_permissions/1, list_user_permissions/3, - list_vhost_permissions/1, list_vhost_permissions/3, - list_user_vhost_permissions/2]). - -%% for testing --export([hashing_module_for_user/1]). - -%%---------------------------------------------------------------------------- - --ifdef(use_specs). - --type(regexp() :: binary()). - --spec(add_user/2 :: (rabbit_types:username(), rabbit_types:password()) -> 'ok'). --spec(delete_user/1 :: (rabbit_types:username()) -> 'ok'). --spec(lookup_user/1 :: (rabbit_types:username()) - -> rabbit_types:ok(rabbit_types:internal_user()) - | rabbit_types:error('not_found')). --spec(change_password/2 :: (rabbit_types:username(), rabbit_types:password()) - -> 'ok'). --spec(clear_password/1 :: (rabbit_types:username()) -> 'ok'). --spec(hash_password/2 :: (module(), rabbit_types:password()) - -> rabbit_types:password_hash()). --spec(change_password_hash/2 :: (rabbit_types:username(), - rabbit_types:password_hash()) -> 'ok'). --spec(set_tags/2 :: (rabbit_types:username(), [atom()]) -> 'ok'). --spec(set_permissions/5 ::(rabbit_types:username(), rabbit_types:vhost(), - regexp(), regexp(), regexp()) -> 'ok'). --spec(clear_permissions/2 :: (rabbit_types:username(), rabbit_types:vhost()) - -> 'ok'). --spec(user_info_keys/0 :: () -> rabbit_types:info_keys()). --spec(perms_info_keys/0 :: () -> rabbit_types:info_keys()). --spec(user_perms_info_keys/0 :: () -> rabbit_types:info_keys()). --spec(vhost_perms_info_keys/0 :: () -> rabbit_types:info_keys()). --spec(user_vhost_perms_info_keys/0 :: () -> rabbit_types:info_keys()). --spec(list_users/0 :: () -> [rabbit_types:infos()]). --spec(list_users/2 :: (reference(), pid()) -> 'ok'). --spec(list_permissions/0 :: () -> [rabbit_types:infos()]). --spec(list_user_permissions/1 :: - (rabbit_types:username()) -> [rabbit_types:infos()]). --spec(list_user_permissions/3 :: - (rabbit_types:username(), reference(), pid()) -> 'ok'). --spec(list_vhost_permissions/1 :: - (rabbit_types:vhost()) -> [rabbit_types:infos()]). --spec(list_vhost_permissions/3 :: - (rabbit_types:vhost(), reference(), pid()) -> 'ok'). --spec(list_user_vhost_permissions/2 :: - (rabbit_types:username(), rabbit_types:vhost()) - -> [rabbit_types:infos()]). - --endif. - -%%---------------------------------------------------------------------------- -%% Implementation of rabbit_auth_backend - -%% Returns a password hashing module for the user record provided. If -%% there is no information in the record, we consider it to be legacy -%% (inserted by a version older than 3.6.0) and fall back to MD5, the -%% now obsolete hashing function. -hashing_module_for_user(#internal_user{ - hashing_algorithm = ModOrUndefined}) -> - rabbit_password:hashing_mod(ModOrUndefined). - -user_login_authentication(Username, []) -> - internal_check_user_login(Username, fun(_) -> true end); -user_login_authentication(Username, [{password, Cleartext}]) -> - internal_check_user_login( - Username, - fun (#internal_user{password_hash = <<Salt:4/binary, Hash/binary>>} = U) -> - Hash =:= rabbit_password:salted_hash( - hashing_module_for_user(U), Salt, Cleartext); - (#internal_user{}) -> - false - end); -user_login_authentication(Username, AuthProps) -> - exit({unknown_auth_props, Username, AuthProps}). - -user_login_authorization(Username) -> - case user_login_authentication(Username, []) of - {ok, #auth_user{impl = Impl, tags = Tags}} -> {ok, Impl, Tags}; - Else -> Else - end. - -internal_check_user_login(Username, Fun) -> - Refused = {refused, "user '~s' - invalid credentials", [Username]}, - case lookup_user(Username) of - {ok, User = #internal_user{tags = Tags}} -> - case Fun(User) of - true -> {ok, #auth_user{username = Username, - tags = Tags, - impl = none}}; - _ -> Refused - end; - {error, not_found} -> - Refused - end. - -check_vhost_access(#auth_user{username = Username}, VHostPath, _Sock) -> - case mnesia:dirty_read({rabbit_user_permission, - #user_vhost{username = Username, - virtual_host = VHostPath}}) of - [] -> false; - [_R] -> true - end. - -check_resource_access(#auth_user{username = Username}, - #resource{virtual_host = VHostPath, name = Name}, - Permission) -> - case mnesia:dirty_read({rabbit_user_permission, - #user_vhost{username = Username, - virtual_host = VHostPath}}) of - [] -> - false; - [#user_permission{permission = P}] -> - PermRegexp = case element(permission_index(Permission), P) of - %% <<"^$">> breaks Emacs' erlang mode - <<"">> -> <<$^, $$>>; - RE -> RE - end, - case re:run(Name, PermRegexp, [{capture, none}]) of - match -> true; - nomatch -> false - end - end. - -permission_index(configure) -> #permission.configure; -permission_index(write) -> #permission.write; -permission_index(read) -> #permission.read. - -%%---------------------------------------------------------------------------- -%% Manipulation of the user database - -add_user(Username, Password) -> - rabbit_log:info("Creating user '~s'~n", [Username]), - %% hash_password will pick the hashing function configured for us - %% but we also need to store a hint as part of the record, so we - %% retrieve it here one more time - HashingMod = rabbit_password:hashing_mod(), - User = #internal_user{username = Username, - password_hash = hash_password(HashingMod, Password), - tags = [], - hashing_algorithm = HashingMod}, - R = rabbit_misc:execute_mnesia_transaction( - fun () -> - case mnesia:wread({rabbit_user, Username}) of - [] -> - ok = mnesia:write(rabbit_user, User, write); - _ -> - mnesia:abort({user_already_exists, Username}) - end - end), - rabbit_event:notify(user_created, [{name, Username}]), - R. - -delete_user(Username) -> - rabbit_log:info("Deleting user '~s'~n", [Username]), - R = rabbit_misc:execute_mnesia_transaction( - rabbit_misc:with_user( - Username, - fun () -> - ok = mnesia:delete({rabbit_user, Username}), - [ok = mnesia:delete_object( - rabbit_user_permission, R, write) || - R <- mnesia:match_object( - rabbit_user_permission, - #user_permission{user_vhost = #user_vhost{ - username = Username, - virtual_host = '_'}, - permission = '_'}, - write)], - ok - end)), - rabbit_event:notify(user_deleted, [{name, Username}]), - R. - -lookup_user(Username) -> - rabbit_misc:dirty_read({rabbit_user, Username}). - -change_password(Username, Password) -> - rabbit_log:info("Changing password for '~s'~n", [Username]), - HashingAlgorithm = rabbit_password:hashing_mod(), - R = change_password_hash(Username, - hash_password(rabbit_password:hashing_mod(), - Password), - HashingAlgorithm), - rabbit_event:notify(user_password_changed, [{name, Username}]), - R. - -clear_password(Username) -> - rabbit_log:info("Clearing password for '~s'~n", [Username]), - R = change_password_hash(Username, <<"">>), - rabbit_event:notify(user_password_cleared, [{name, Username}]), - R. - -hash_password(HashingMod, Cleartext) -> - rabbit_password:hash(HashingMod, Cleartext). - -change_password_hash(Username, PasswordHash) -> - change_password_hash(Username, PasswordHash, rabbit_password:hashing_mod()). - - -change_password_hash(Username, PasswordHash, HashingAlgorithm) -> - update_user(Username, fun(User) -> - User#internal_user{ - password_hash = PasswordHash, - hashing_algorithm = HashingAlgorithm } - end). - -set_tags(Username, Tags) -> - rabbit_log:info("Setting user tags for user '~s' to ~p~n", - [Username, Tags]), - R = update_user(Username, fun(User) -> - User#internal_user{tags = Tags} - end), - rabbit_event:notify(user_tags_set, [{name, Username}, {tags, Tags}]), - R. - -set_permissions(Username, VHostPath, ConfigurePerm, WritePerm, ReadPerm) -> - rabbit_log:info("Setting permissions for " - "'~s' in '~s' to '~s', '~s', '~s'~n", - [Username, VHostPath, ConfigurePerm, WritePerm, ReadPerm]), - lists:map( - fun (RegexpBin) -> - Regexp = binary_to_list(RegexpBin), - case re:compile(Regexp) of - {ok, _} -> ok; - {error, Reason} -> throw({error, {invalid_regexp, - Regexp, Reason}}) - end - end, [ConfigurePerm, WritePerm, ReadPerm]), - R = rabbit_misc:execute_mnesia_transaction( - rabbit_misc:with_user_and_vhost( - Username, VHostPath, - fun () -> ok = mnesia:write( - rabbit_user_permission, - #user_permission{user_vhost = #user_vhost{ - username = Username, - virtual_host = VHostPath}, - permission = #permission{ - configure = ConfigurePerm, - write = WritePerm, - read = ReadPerm}}, - write) - end)), - rabbit_event:notify(permission_created, [{user, Username}, - {vhost, VHostPath}, - {configure, ConfigurePerm}, - {write, WritePerm}, - {read, ReadPerm}]), - R. - -clear_permissions(Username, VHostPath) -> - R = rabbit_misc:execute_mnesia_transaction( - rabbit_misc:with_user_and_vhost( - Username, VHostPath, - fun () -> - ok = mnesia:delete({rabbit_user_permission, - #user_vhost{username = Username, - virtual_host = VHostPath}}) - end)), - rabbit_event:notify(permission_deleted, [{user, Username}, - {vhost, VHostPath}]), - R. - - -update_user(Username, Fun) -> - rabbit_misc:execute_mnesia_transaction( - rabbit_misc:with_user( - Username, - fun () -> - {ok, User} = lookup_user(Username), - ok = mnesia:write(rabbit_user, Fun(User), write) - end)). - -%%---------------------------------------------------------------------------- -%% Listing - --define(PERMS_INFO_KEYS, [configure, write, read]). --define(USER_INFO_KEYS, [user, tags]). - -user_info_keys() -> ?USER_INFO_KEYS. - -perms_info_keys() -> [user, vhost | ?PERMS_INFO_KEYS]. -vhost_perms_info_keys() -> [user | ?PERMS_INFO_KEYS]. -user_perms_info_keys() -> [vhost | ?PERMS_INFO_KEYS]. -user_vhost_perms_info_keys() -> ?PERMS_INFO_KEYS. - -list_users() -> - [extract_internal_user_params(U) || - U <- mnesia:dirty_match_object(rabbit_user, #internal_user{_ = '_'})]. - -list_users(Ref, AggregatorPid) -> - rabbit_control_misc:emitting_map( - AggregatorPid, Ref, - fun(U) -> extract_internal_user_params(U) end, - mnesia:dirty_match_object(rabbit_user, #internal_user{_ = '_'})). - -list_permissions() -> - list_permissions(perms_info_keys(), match_user_vhost('_', '_')). - -list_permissions(Keys, QueryThunk) -> - [extract_user_permission_params(Keys, U) || - %% TODO: use dirty ops instead - U <- rabbit_misc:execute_mnesia_transaction(QueryThunk)]. - -list_permissions(Keys, QueryThunk, Ref, AggregatorPid) -> - rabbit_control_misc:emitting_map( - AggregatorPid, Ref, fun(U) -> extract_user_permission_params(Keys, U) end, - %% TODO: use dirty ops instead - rabbit_misc:execute_mnesia_transaction(QueryThunk)). - -filter_props(Keys, Props) -> [T || T = {K, _} <- Props, lists:member(K, Keys)]. - -list_user_permissions(Username) -> - list_permissions( - user_perms_info_keys(), - rabbit_misc:with_user(Username, match_user_vhost(Username, '_'))). - -list_user_permissions(Username, Ref, AggregatorPid) -> - list_permissions( - user_perms_info_keys(), - rabbit_misc:with_user(Username, match_user_vhost(Username, '_')), - Ref, AggregatorPid). - -list_vhost_permissions(VHostPath) -> - list_permissions( - vhost_perms_info_keys(), - rabbit_vhost:with(VHostPath, match_user_vhost('_', VHostPath))). - -list_vhost_permissions(VHostPath, Ref, AggregatorPid) -> - list_permissions( - vhost_perms_info_keys(), - rabbit_vhost:with(VHostPath, match_user_vhost('_', VHostPath)), - Ref, AggregatorPid). - -list_user_vhost_permissions(Username, VHostPath) -> - list_permissions( - user_vhost_perms_info_keys(), - rabbit_misc:with_user_and_vhost( - Username, VHostPath, match_user_vhost(Username, VHostPath))). - -extract_user_permission_params(Keys, #user_permission{ - user_vhost = - #user_vhost{username = Username, - virtual_host = VHostPath}, - permission = #permission{ - configure = ConfigurePerm, - write = WritePerm, - read = ReadPerm}}) -> - filter_props(Keys, [{user, Username}, - {vhost, VHostPath}, - {configure, ConfigurePerm}, - {write, WritePerm}, - {read, ReadPerm}]). - -extract_internal_user_params(#internal_user{username = Username, tags = Tags}) -> - [{user, Username}, {tags, Tags}]. - -match_user_vhost(Username, VHostPath) -> - fun () -> mnesia:match_object( - rabbit_user_permission, - #user_permission{user_vhost = #user_vhost{ - username = Username, - virtual_host = VHostPath}, - permission = '_'}, - read) - end. diff --git a/src/rabbit_cli.erl b/src/rabbit_cli.erl index 4aad3c0916..6679d9329e 100644 --- a/src/rabbit_cli.erl +++ b/src/rabbit_cli.erl @@ -255,14 +255,10 @@ print_badrpc_diagnostics(Nodes) -> %% a timeout unless we set our ticktime to be the same. So let's do %% that. rpc_call(Node, Mod, Fun, Args) -> - rpc_call(Node, Mod, Fun, Args, ?RPC_TIMEOUT). + rabbit_misc:rpc_call(Node, Mod, Fun, Args). rpc_call(Node, Mod, Fun, Args, Timeout) -> - case rpc:call(Node, net_kernel, get_net_ticktime, [], Timeout) of - {badrpc, _} = E -> E; - Time -> net_kernel:set_net_ticktime(Time, 0), - rpc:call(Node, Mod, Fun, Args, Timeout) - end. + rabbit_misc:rpc_call(Node, Mod, Fun, Args, Timeout). rpc_call(Node, Mod, Fun, Args, Ref, Pid, Timeout) -> - rpc_call(Node, Mod, Fun, Args++[Ref, Pid], Timeout). + rabbit_misc:rpc_call(Node, Mod, Fun, Args, Ref, Pid, Timeout). diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl index c6e39b17f5..b805d21e48 100644 --- a/src/rabbit_control_main.erl +++ b/src/rabbit_control_main.erl @@ -17,12 +17,13 @@ -module(rabbit_control_main). -include("rabbit.hrl"). -include("rabbit_cli.hrl"). +-include("rabbit_misc.hrl"). -export([start/0, stop/0, parse_arguments/2, action/5, action/6, sync_queue/1, cancel_sync_queue/1, become/1, purge_queue/1]). --import(rabbit_cli, [rpc_call/4, rpc_call/5, rpc_call/7]). +-import(rabbit_misc, [rpc_call/4, rpc_call/5, rpc_call/7]). -define(EXTERNAL_CHECK_INTERVAL, 1000). @@ -83,6 +84,7 @@ report, set_cluster_name, eval, + node_health_check, close_connection, {trace_on, [?VHOST_DEF]}, @@ -111,7 +113,7 @@ [stop, stop_app, start_app, wait, reset, force_reset, rotate_logs, join_cluster, change_cluster_node_type, update_cluster_nodes, forget_cluster_node, rename_cluster_node, cluster_status, status, - environment, eval, force_boot, help]). + environment, eval, force_boot, help, node_health_check]). -define(COMMANDS_WITH_TIMEOUT, [list_user_permissions, list_policies, list_queues, list_exchanges, @@ -547,6 +549,17 @@ action(eval, Node, [Expr], _Opts, _Inform) -> action(help, _Node, _Args, _Opts, _Inform) -> io:format("~s", [rabbit_ctl_usage:usage()]); +action(node_health_check, Node, _Args, _Opts, Inform) -> + Inform("Checking health of node ~p", [Node]), + try + rabbit_health_check:node(Node), + io:format("Health check passed~n") + catch + {node_is_ko, ErrorMsg, ErrorCode} -> + io:format("Heath check failed:~n~s~n", [ErrorMsg]), + halt(ErrorCode) + end; + action(Command, Node, Args, Opts, Inform) -> %% For backward compatibility, run commands accepting a timeout with %% the default timeout. @@ -570,7 +583,8 @@ action(list_permissions, Node, [], Opts, Inform, Timeout) -> VHost = proplists:get_value(?VHOST_OPT, Opts), Inform("Listing permissions in vhost \"~s\"", [VHost]), call(Node, {rabbit_auth_backend_internal, list_vhost_permissions, [VHost]}, - rabbit_auth_backend_internal:vhost_perms_info_keys(), true, Timeout); + rabbit_auth_backend_internal:vhost_perms_info_keys(), true, Timeout, + true); action(list_parameters, Node, [], Opts, Inform, Timeout) -> VHostArg = list_to_binary(proplists:get_value(?VHOST_OPT, Opts)), @@ -595,7 +609,8 @@ action(list_user_permissions, _Node, _Args = [], _Opts, _Inform, _Timeout) -> action(list_user_permissions, Node, Args = [_Username], _Opts, Inform, Timeout) -> Inform("Listing permissions for user ~p", Args), call(Node, {rabbit_auth_backend_internal, list_user_permissions, Args}, - rabbit_auth_backend_internal:user_perms_info_keys(), true, Timeout); + rabbit_auth_backend_internal:user_perms_info_keys(), true, Timeout, + true); action(list_queues, Node, Args, Opts, Inform, Timeout) -> Inform("Listing queues", []), @@ -738,20 +753,22 @@ default_if_empty(List, Default) when is_list(List) -> true -> [list_to_atom(X) || X <- List] end. -display_info_message(Result, InfoItemKeys) -> - display_row([format_info_item( - case proplists:lookup(X, Result) of - none when is_list(Result), length(Result) > 0 -> - exit({error, {bad_info_key, X}}); - none -> Result; - {X, Value} -> Value - end) || X <- InfoItemKeys]). +display_info_message(IsEscaped) -> + fun(Result, InfoItemKeys) -> + display_row([format_info_item( + case proplists:lookup(X, Result) of + none when is_list(Result), length(Result) > 0 -> + exit({error, {bad_info_key, X}}); + none -> Result; + {X, Value} -> Value + end, IsEscaped) || X <- InfoItemKeys]) + end. display_info_list(Results, InfoItemKeys) when is_list(Results) -> lists:foreach( fun (Result) -> display_row( - [format_info_item(proplists:get_value(X, Result)) || - X <- InfoItemKeys]) + [format_info_item(proplists:get_value(X, Result), true) + || X <- InfoItemKeys]) end, lists:sort(Results)), ok; display_info_list(Other, _) -> @@ -764,32 +781,33 @@ display_row(Row) -> -define(IS_U8(X), (X >= 0 andalso X =< 255)). -define(IS_U16(X), (X >= 0 andalso X =< 65535)). -format_info_item(#resource{name = Name}) -> - escape(Name); -format_info_item({N1, N2, N3, N4} = Value) when +format_info_item(#resource{name = Name}, IsEscaped) -> + escape(Name, IsEscaped); +format_info_item({N1, N2, N3, N4} = Value, _IsEscaped) when ?IS_U8(N1), ?IS_U8(N2), ?IS_U8(N3), ?IS_U8(N4) -> rabbit_misc:ntoa(Value); -format_info_item({K1, K2, K3, K4, K5, K6, K7, K8} = Value) when +format_info_item({K1, K2, K3, K4, K5, K6, K7, K8} = Value, _IsEscaped) when ?IS_U16(K1), ?IS_U16(K2), ?IS_U16(K3), ?IS_U16(K4), ?IS_U16(K5), ?IS_U16(K6), ?IS_U16(K7), ?IS_U16(K8) -> rabbit_misc:ntoa(Value); -format_info_item(Value) when is_pid(Value) -> +format_info_item(Value, _IsEscaped) when is_pid(Value) -> rabbit_misc:pid_to_string(Value); -format_info_item(Value) when is_binary(Value) -> - escape(Value); -format_info_item(Value) when is_atom(Value) -> - escape(atom_to_list(Value)); +format_info_item(Value, IsEscaped) when is_binary(Value) -> + escape(Value, IsEscaped); +format_info_item(Value, IsEscaped) when is_atom(Value) -> + escape(atom_to_list(Value), IsEscaped); format_info_item([{TableEntryKey, TableEntryType, _TableEntryValue} | _] = - Value) when is_binary(TableEntryKey) andalso - is_atom(TableEntryType) -> - io_lib:format("~1000000000000p", [prettify_amqp_table(Value)]); -format_info_item([T | _] = Value) + Value, IsEscaped) when is_binary(TableEntryKey) andalso + is_atom(TableEntryType) -> + io_lib:format("~1000000000000p", [prettify_amqp_table(Value, IsEscaped)]); +format_info_item([T | _] = Value, IsEscaped) when is_tuple(T) orelse is_pid(T) orelse is_binary(T) orelse is_atom(T) orelse is_list(T) -> "[" ++ lists:nthtail(2, lists:append( - [", " ++ format_info_item(E) || E <- Value])) ++ "]"; -format_info_item(Value) -> + [", " ++ format_info_item(E, IsEscaped) + || E <- Value])) ++ "]"; +format_info_item(Value, _IsEscaped) -> io_lib:format("~w", [Value]). display_call_result(Node, MFA) -> @@ -820,9 +838,12 @@ call(Node, {Mod, Fun, Args}) -> rpc_call(Node, Mod, Fun, lists:map(fun list_to_binary_utf8/1, Args)). call(Node, {Mod, Fun, Args}, InfoKeys, Timeout) -> - call(Node, {Mod, Fun, Args}, InfoKeys, false, Timeout). + call(Node, {Mod, Fun, Args}, InfoKeys, false, Timeout, false). call(Node, {Mod, Fun, Args}, InfoKeys, ToBinUtf8, Timeout) -> + call(Node, {Mod, Fun, Args}, InfoKeys, ToBinUtf8, Timeout, false). + +call(Node, {Mod, Fun, Args}, InfoKeys, ToBinUtf8, Timeout, IsEscaped) -> Args0 = case ToBinUtf8 of true -> lists:map(fun list_to_binary_utf8/1, Args); false -> Args @@ -842,7 +863,7 @@ call(Node, {Mod, Fun, Args}, InfoKeys, ToBinUtf8, Timeout) -> end end), rabbit_control_misc:wait_for_info_messages( - Pid, Ref, InfoKeys, fun display_info_message/2, Timeout). + Pid, Ref, InfoKeys, display_info_message(IsEscaped), Timeout). list_to_binary_utf8(L) -> B = list_to_binary(L), @@ -855,9 +876,14 @@ list_to_binary_utf8(L) -> %% characters. We don't escape characters above 127, since they may %% form part of UTF-8 strings. -escape(Atom) when is_atom(Atom) -> escape(atom_to_list(Atom)); -escape(Bin) when is_binary(Bin) -> escape(binary_to_list(Bin)); -escape(L) when is_list(L) -> escape_char(lists:reverse(L), []). +escape(Atom, IsEscaped) when is_atom(Atom) -> + escape(atom_to_list(Atom), IsEscaped); +escape(Bin, IsEscaped) when is_binary(Bin) -> + escape(binary_to_list(Bin), IsEscaped); +escape(L, false) when is_list(L) -> + escape_char(lists:reverse(L), []); +escape(L, true) when is_list(L) -> + L. escape_char([$\\ | T], Acc) -> escape_char(T, [$\\, $\\ | Acc]); @@ -869,14 +895,18 @@ escape_char([X | T], Acc) -> escape_char([], Acc) -> Acc. -prettify_amqp_table(Table) -> - [{escape(K), prettify_typed_amqp_value(T, V)} || {K, T, V} <- Table]. - -prettify_typed_amqp_value(longstr, Value) -> escape(Value); -prettify_typed_amqp_value(table, Value) -> prettify_amqp_table(Value); -prettify_typed_amqp_value(array, Value) -> [prettify_typed_amqp_value(T, V) || - {T, V} <- Value]; -prettify_typed_amqp_value(_Type, Value) -> Value. +prettify_amqp_table(Table, IsEscaped) -> + [{escape(K, IsEscaped), prettify_typed_amqp_value(T, V, IsEscaped)} + || {K, T, V} <- Table]. + +prettify_typed_amqp_value(longstr, Value, IsEscaped) -> + escape(Value, IsEscaped); +prettify_typed_amqp_value(table, Value, IsEscaped) -> + prettify_amqp_table(Value, IsEscaped); +prettify_typed_amqp_value(array, Value, IsEscaped) -> + [prettify_typed_amqp_value(T, V, IsEscaped) || {T, V} <- Value]; +prettify_typed_amqp_value(_Type, Value, _IsEscaped) -> + Value. split_list([]) -> []; split_list([_]) -> exit(even_list_needed); diff --git a/src/rabbit_plugins_main.erl b/src/rabbit_plugins_main.erl index 4aeed4826c..e248989a7a 100644 --- a/src/rabbit_plugins_main.erl +++ b/src/rabbit_plugins_main.erl @@ -173,7 +173,7 @@ format_plugins(Node, Pattern, Opts, #cli{all = All, EnabledImplicitly = Implicit -- Enabled, {StatusMsg, Running} = - case rabbit_cli:rpc_call(Node, rabbit_plugins, active, []) of + case rabbit_misc:rpc_call(Node, rabbit_plugins, active, []) of {badrpc, _} -> {"[failed to contact ~s - status not shown]", []}; Active -> {"* = running on ~s", Active} end, @@ -279,7 +279,7 @@ sync(Node, ForceOnline, #cli{file = File}) -> rpc_call(Node, Online, Mod, Fun, Args) -> io:format("~nApplying plugin configuration to ~s...", [Node]), - case rabbit_cli:rpc_call(Node, Mod, Fun, Args) of + case rabbit_misc:rpc_call(Node, Mod, Fun, Args) of {ok, [], []} -> io:format(" nothing to do.~n", []); {ok, Start, []} -> diff --git a/src/rabbit_types.erl b/src/rabbit_types.erl deleted file mode 100644 index 3dcb63cbb9..0000000000 --- a/src/rabbit_types.erl +++ /dev/null @@ -1,168 +0,0 @@ -%% The contents of this file are subject to the Mozilla Public License -%% Version 1.1 (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.mozilla.org/MPL/ -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and -%% limitations under the License. -%% -%% The Original Code is RabbitMQ. -%% -%% The Initial Developer of the Original Code is GoPivotal, Inc. -%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. -%% - --module(rabbit_types). - --include("rabbit.hrl"). - --ifdef(use_specs). - --export_type([maybe/1, info/0, infos/0, info_key/0, info_keys/0, - message/0, msg_id/0, basic_message/0, - delivery/0, content/0, decoded_content/0, undecoded_content/0, - unencoded_content/0, encoded_content/0, message_properties/0, - vhost/0, ctag/0, amqp_error/0, r/1, r2/2, r3/3, listener/0, - binding/0, binding_source/0, binding_destination/0, - amqqueue/0, exchange/0, - connection/0, protocol/0, auth_user/0, user/0, internal_user/0, - username/0, password/0, password_hash/0, - ok/1, error/1, ok_or_error/1, ok_or_error2/2, ok_pid_or_error/0, - channel_exit/0, connection_exit/0, mfargs/0, proc_name/0, - proc_type_and_name/0, timestamp/0]). - --type(maybe(T) :: T | 'none'). --type(timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}). --type(vhost() :: binary()). --type(ctag() :: binary()). - -%% TODO: make this more precise by tying specific class_ids to -%% specific properties --type(undecoded_content() :: - #content{class_id :: rabbit_framing:amqp_class_id(), - properties :: 'none', - properties_bin :: binary(), - payload_fragments_rev :: [binary()]} | - #content{class_id :: rabbit_framing:amqp_class_id(), - properties :: rabbit_framing:amqp_property_record(), - properties_bin :: 'none', - payload_fragments_rev :: [binary()]}). --type(unencoded_content() :: undecoded_content()). --type(decoded_content() :: - #content{class_id :: rabbit_framing:amqp_class_id(), - properties :: rabbit_framing:amqp_property_record(), - properties_bin :: maybe(binary()), - payload_fragments_rev :: [binary()]}). --type(encoded_content() :: - #content{class_id :: rabbit_framing:amqp_class_id(), - properties :: maybe(rabbit_framing:amqp_property_record()), - properties_bin :: binary(), - payload_fragments_rev :: [binary()]}). --type(content() :: undecoded_content() | decoded_content()). --type(msg_id() :: rabbit_guid:guid()). --type(basic_message() :: - #basic_message{exchange_name :: rabbit_exchange:name(), - routing_keys :: [rabbit_router:routing_key()], - content :: content(), - id :: msg_id(), - is_persistent :: boolean()}). --type(message() :: basic_message()). --type(delivery() :: - #delivery{mandatory :: boolean(), - sender :: pid(), - message :: message()}). --type(message_properties() :: - #message_properties{expiry :: pos_integer() | 'undefined', - needs_confirming :: boolean()}). - --type(info_key() :: atom()). --type(info_keys() :: [info_key()]). - --type(info() :: {info_key(), any()}). --type(infos() :: [info()]). - --type(amqp_error() :: - #amqp_error{name :: rabbit_framing:amqp_exception(), - explanation :: string(), - method :: rabbit_framing:amqp_method_name()}). - --type(r(Kind) :: - r2(vhost(), Kind)). --type(r2(VirtualHost, Kind) :: - r3(VirtualHost, Kind, rabbit_misc:resource_name())). --type(r3(VirtualHost, Kind, Name) :: - #resource{virtual_host :: VirtualHost, - kind :: Kind, - name :: Name}). - --type(listener() :: - #listener{node :: node(), - protocol :: atom(), - host :: rabbit_networking:hostname(), - port :: rabbit_networking:ip_port()}). - --type(binding_source() :: rabbit_exchange:name()). --type(binding_destination() :: rabbit_amqqueue:name() | rabbit_exchange:name()). - --type(binding() :: - #binding{source :: rabbit_exchange:name(), - destination :: binding_destination(), - key :: rabbit_binding:key(), - args :: rabbit_framing:amqp_table()}). - --type(amqqueue() :: - #amqqueue{name :: rabbit_amqqueue:name(), - durable :: boolean(), - auto_delete :: boolean(), - exclusive_owner :: rabbit_types:maybe(pid()), - arguments :: rabbit_framing:amqp_table(), - pid :: rabbit_types:maybe(pid()), - slave_pids :: [pid()]}). - --type(exchange() :: - #exchange{name :: rabbit_exchange:name(), - type :: rabbit_exchange:type(), - durable :: boolean(), - auto_delete :: boolean(), - arguments :: rabbit_framing:amqp_table()}). - --type(connection() :: pid()). - --type(protocol() :: rabbit_framing:protocol()). - --type(auth_user() :: - #auth_user{username :: username(), - tags :: [atom()], - impl :: any()}). - --type(user() :: - #user{username :: username(), - tags :: [atom()], - authz_backends :: [{atom(), any()}]}). - --type(internal_user() :: - #internal_user{username :: username(), - password_hash :: password_hash(), - tags :: [atom()]}). - --type(username() :: binary()). --type(password() :: binary()). --type(password_hash() :: binary()). - --type(ok(A) :: {'ok', A}). --type(error(A) :: {'error', A}). --type(ok_or_error(A) :: 'ok' | error(A)). --type(ok_or_error2(A, B) :: ok(A) | error(B)). --type(ok_pid_or_error() :: ok_or_error2(pid(), any())). - --type(channel_exit() :: no_return()). --type(connection_exit() :: no_return()). - --type(mfargs() :: {atom(), atom(), [any()]}). - --type(proc_name() :: term()). --type(proc_type_and_name() :: {atom(), proc_name()}). - --endif. % use_specs |
