summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bakken <lbakken@pivotal.io>2017-06-20 15:01:58 -0700
committerLuke Bakken <lbakken@pivotal.io>2017-06-20 15:01:58 -0700
commit59ce657abcdbbed66799f466792657709baae37d (patch)
treea98982fb337c24aef536955fb31f3afa1a41a524
parentdd18cf3540bc4e87b4a5d586a6c88a4bf8b88874 (diff)
parent72415b1c9446db5ad38b7d70a45fec6942682ec0 (diff)
downloadrabbitmq-server-git-59ce657abcdbbed66799f466792657709baae37d.tar.gz
Merge branch 'master' into rabbitmq-server-1246-master
-rw-r--r--Makefile3
-rw-r--r--docs/rabbitmqctl.894
-rw-r--r--priv/schema/rabbit.schema (renamed from priv/schema/rabbitmq.schema)8
-rw-r--r--scripts/rabbitmq-env.bat3
-rwxr-xr-xscripts/rabbitmq-server4
-rw-r--r--scripts/rabbitmq-server.bat4
-rw-r--r--scripts/rabbitmq-service.bat4
-rw-r--r--src/rabbit.erl2
-rw-r--r--src/rabbit_node_monitor.erl40
-rw-r--r--src/rabbit_vm.erl125
-rw-r--r--src/term_to_binary_compat.erl13
-rw-r--r--src/vm_memory_monitor.erl13
-rw-r--r--test/config_schema_SUITE_data/rabbit.snippets12
-rw-r--r--test/partitions_SUITE.erl38
-rw-r--r--test/term_to_binary_compat_prop_SUITE.erl59
-rw-r--r--test/topic_permission_SUITE.erl32
16 files changed, 386 insertions, 68 deletions
diff --git a/Makefile b/Makefile
index 9540566762..61c8fa4b53 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ define PROJECT_ENV
{ssl_options, []},
{vm_memory_high_watermark, 0.4},
{vm_memory_high_watermark_paging_ratio, 0.5},
+ {vm_memory_calculation_strategy, rss},
{memory_monitor_interval, 2500},
{disk_free_limit, 50000000}, %% 50MB
{msg_store_index_module, rabbit_msg_store_ets_index},
@@ -125,7 +126,7 @@ define PROJECT_ENV
]
endef
-LOCAL_DEPS = sasl mnesia os_mon
+LOCAL_DEPS = sasl mnesia os_mon inets
BUILD_DEPS = rabbitmq_cli
DEPS = ranch lager rabbit_common
TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers amqp_client meck proper
diff --git a/docs/rabbitmqctl.8 b/docs/rabbitmqctl.8
index e12f6f496f..91b99560d6 100644
--- a/docs/rabbitmqctl.8
+++ b/docs/rabbitmqctl.8
@@ -784,6 +784,100 @@ has been granted access, and the permissions the user has for operations
on resources in these virtual hosts:
.sp
.Dl rabbitmqctl list_user_permissions tonyg
+.\" ------------------------------------
+.It Cm set_topic_permissions Oo Fl p Ar vhost Oc Ar user Ar exchange Ar write Ar read
+.Bl -tag -width Ds
+.It Ar vhost
+The name of the virtual host to which to grant the user access,
+defaulting to
+.Qq / .
+.It Ar user
+The name of the user the permissions apply to in the target virtual host.
+.It Ar exchange
+The name of the topic exchange the authorisation check will be applied to.
+.It Ar write
+A regular expression matching the routing key of the published message.
+.It Ar read
+A regular expression matching the routing key of the consumed message.
+.El
+.Pp
+Sets user topic permissions.
+.Pp
+For example, this command instructs the RabbitMQ broker to let the
+user named
+.Qq tonyg
+publish and consume messages going through the
+.Qq amp.topic
+exchange of the
+.Qq /myvhost
+virtual host with a routing key starting with
+.Qq tonyg- :
+.sp
+.Dl rabbitmqctl set_topic_permissions -p /myvhost tonyg amq.topic Qo ^tonyg-.* Qc Qo ^tonyg-.* Qc
+.Pp
+Topic permissions support variable expansion for the following variables:
+username, vhost, and client_id. Note that client_id is expanded only when using MQTT.
+The previous example could be made more generic by using
+.Qq ^{username}-.* :
+.sp
+.Dl rabbitmqctl set_topic_permissions -p /myvhost tonyg amq.topic Qo ^{username}-.* Qc Qo ^{username}-.* Qc
+.\" ------------------------------------
+.It Cm clear_topic_permissions Oo Fl p Ar vhost Oc Ar username Oo Ar exchange Oc
+.Bl -tag -width Ds
+.It Ar vhost
+The name of the virtual host to which to clear the topic permissions,
+defaulting to
+.Qq / .
+.It Ar username
+The name of the user to clear topic permissions to the specified virtual host.
+.It Ar exchange
+The name of the topic exchange to clear topic permissions, defaulting to all the
+topic exchanges the given user has topic permissions for.
+.El
+.Pp
+Clear user topic permissions.
+.Pp
+For example, this command instructs the RabbitMQ broker to remove topic permissions for user
+named
+.Qq tonyg
+for the topic exchange
+.Qq amq.topic
+in the virtual host called
+.Qq /myvhost :
+.sp
+.Dl rabbitmqctl clear_topic_permissions -p /myvhost tonyg amq.topic
+.\" ------------------------------------
+.It Cm list_topic_permissions Op Fl p Ar vhost
+.Bl -tag -width Ds
+.It Ar vhost
+The name of the virtual host for which to list the users topic permissions.
+Defaults to
+.Qq / .
+.El
+.Pp
+Lists topic permissions in a virtual host.
+.Pp
+For example, this command instructs the RabbitMQ broker to list all the
+users which have been granted topic permissions in the virtual host called
+.Qq /myvhost:
+.sp
+.Dl rabbitmqctl list_topic_permissions -p /myvhost
+.\" ------------------------------------
+.It Cm list_user_topic_permissions Ar username
+.Bl -tag -width Ds
+.It Ar username
+The name of the user for which to list the topic permissions.
+.El
+.Pp
+Lists user topic permissions.
+.Pp
+For example, this command instructs the RabbitMQ broker to list all the
+virtual hosts to which the user named
+.Qq tonyg
+has been granted access, and the topic permissions the user has in these virtual hosts:
+.sp
+.Dl rabbitmqctl list_topic_user_permissions tonyg
+
.El
.Ss Parameter Management
Certain features of RabbitMQ (such as the federation plugin) are
diff --git a/priv/schema/rabbitmq.schema b/priv/schema/rabbit.schema
index 985c77b9a8..e3eff6fb59 100644
--- a/priv/schema/rabbitmq.schema
+++ b/priv/schema/rabbit.schema
@@ -683,6 +683,14 @@ end}.
{mapping, "memory_monitor_interval", "rabbit.memory_monitor_interval",
[{datatype, integer}]}.
+%% When set to rss, RabbitMQ will display the memory usage as reported
+%% by the operating system (RSS value), not by the Erlang VM.
+%%
+%% {vm_memory_calculation_strategy, rss},
+
+{mapping, "vm_memory_calculation_strategy", "rabbit.vm_memory_calculation_strategy",
+ [{datatype, {enum, [rss, erlang]}}]}.
+
%% Set disk free limit (in bytes). Once free disk space reaches this
%% lower bound, a disk alarm will be set - see the documentation
%% listed above for more details.
diff --git a/scripts/rabbitmq-env.bat b/scripts/rabbitmq-env.bat
index 9d7a724318..e3fddbb3eb 100644
--- a/scripts/rabbitmq-env.bat
+++ b/scripts/rabbitmq-env.bat
@@ -202,7 +202,6 @@ if "!RABBITMQ_SCHEMA_DIR!" == "" (
)
)
-
REM [ "x" = "x$RABBITMQ_LOG_BASE" ] && RABBITMQ_LOG_BASE=${LOG_BASE}
if "!RABBITMQ_LOG_BASE!"=="" (
if "!LOG_BASE!"=="" (
@@ -418,7 +417,7 @@ exit /b
:filter_path
REM Ensure ERL_LIBS begins with valid path
-IF [%ERL_LIBS%] EQU [] (
+IF "%ERL_LIBS%"=="" (
set ERL_LIBS=%~dps1%~n1%~x1
) else (
set ERL_LIBS=%ERL_LIBS%;%~dps1%~n1%~x1
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server
index a318b55d75..d307e79138 100755
--- a/scripts/rabbitmq-server
+++ b/scripts/rabbitmq-server
@@ -115,8 +115,8 @@ if [ ! -d ${RABBITMQ_GENERATED_CONFIG_DIR} ]; then
mkdir -p "${RABBITMQ_GENERATED_CONFIG_DIR}"
fi
-if [ ! -f "${RABBITMQ_SCHEMA_DIR}/rabbitmq.schema" ]; then
- cp "${RABBITMQ_HOME}/priv/schema/rabbitmq.schema" "${RABBITMQ_SCHEMA_DIR}"
+if [ ! -f "${RABBITMQ_SCHEMA_DIR}/rabbit.schema" ]; then
+ cp "${RABBITMQ_HOME}/priv/schema/rabbit.schema" "${RABBITMQ_SCHEMA_DIR}"
fi
set -e
diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat
index de25f95bdf..ea417dcad4 100644
--- a/scripts/rabbitmq-server.bat
+++ b/scripts/rabbitmq-server.bat
@@ -79,8 +79,8 @@ if not exist "!RABBITMQ_GENERATED_CONFIG_DIR!" (
mkdir "!RABBITMQ_GENERATED_CONFIG_DIR!"
)
-if not exist "!RABBITMQ_SCHEMA_DIR!\rabbitmq.schema" (
- copy "!RABBITMQ_HOME!\priv\schema\rabbitmq.schema" "!RABBITMQ_SCHEMA_DIR!\rabbitmq.schema"
+if not exist "!RABBITMQ_SCHEMA_DIR!\rabbit.schema" (
+ copy "!RABBITMQ_HOME!\priv\schema\rabbit.schema" "!RABBITMQ_SCHEMA_DIR!\rabbit.schema"
)
set RABBITMQ_EBIN_PATH="-pa !RABBITMQ_EBIN_ROOT!"
diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat
index 624d18d913..2f118205ab 100644
--- a/scripts/rabbitmq-service.bat
+++ b/scripts/rabbitmq-service.bat
@@ -165,8 +165,8 @@ if not exist "!RABBITMQ_GENERATED_CONFIG_DIR!" (
mkdir "!RABBITMQ_GENERATED_CONFIG_DIR!"
)
-if not exist "!RABBITMQ_SCHEMA_DIR!\rabbitmq.schema" (
- copy "!RABBITMQ_HOME!\priv\schema\rabbitmq.schema" "!RABBITMQ_SCHEMA_DIR!\rabbitmq.schema"
+if not exist "!RABBITMQ_SCHEMA_DIR!\rabbit.schema" (
+ copy "!RABBITMQ_HOME!\priv\schema\rabbit.schema" "!RABBITMQ_SCHEMA_DIR!\rabbit.schema"
)
REM Try to create advanced config file, if it doesn't exist
REM It still can fail to be created, but at least not for default install
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 26a69ddeea..138d03f051 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -624,7 +624,7 @@ decrypt_list([Value|Tail], Algo, Acc) ->
stop_apps(Apps) ->
rabbit_log:info(
- lists:flatten(["Stopping RabbitMQ applications and their dependencies in the following order: ~n",
+ lists:flatten(["Stopping RabbitMQ applications and their dependencies in the following order:~n",
[" ~p~n" || _ <- Apps]]),
lists:reverse(Apps)),
ok = app_utils:stop_applications(
diff --git a/src/rabbit_node_monitor.erl b/src/rabbit_node_monitor.erl
index 0eadf0ff59..810df2d1fc 100644
--- a/src/rabbit_node_monitor.erl
+++ b/src/rabbit_node_monitor.erl
@@ -344,8 +344,8 @@ init([]) ->
Nodes = possibly_partitioned_nodes(),
startup_log(Nodes),
Monitors = lists:foldl(fun(Node, Monitors0) ->
- pmon:monitor({rabbit, Node}, Monitors0)
- end, pmon:new(), Nodes),
+ pmon:monitor({rabbit, Node}, Monitors0)
+ end, pmon:new(), Nodes),
{ok, ensure_keepalive_timer(#state{monitors = Monitors,
subscribers = pmon:new(),
partitions = [],
@@ -420,12 +420,12 @@ handle_cast({check_partial_partition, Node, Rep, NodeGUID, MyGUID, RepGUID},
fun () ->
case rpc:call(Node, rabbit, is_running, []) of
{badrpc, _} -> ok;
- _ ->
- rabbit_log:warning("Received a 'DOWN' message"
- " from ~p but still can"
- " communicate with it ~n",
- [Node]),
- cast(Rep, {partial_partition,
+ _ ->
+ rabbit_log:warning("Received a 'DOWN' message"
+ " from ~p but still can"
+ " communicate with it ~n",
+ [Node]),
+ cast(Rep, {partial_partition,
Node, node(), RepGUID})
end
end);
@@ -499,18 +499,18 @@ handle_cast({node_up, Node, NodeType},
rabbit_log:info("rabbit on node ~p up~n", [Node]),
{AllNodes, DiscNodes, RunningNodes} = read_cluster_status(),
write_cluster_status({add_node(Node, AllNodes),
- case NodeType of
- disc -> add_node(Node, DiscNodes);
- ram -> DiscNodes
- end,
- add_node(Node, RunningNodes)}),
+ case NodeType of
+ disc -> add_node(Node, DiscNodes);
+ ram -> DiscNodes
+ end,
+ add_node(Node, RunningNodes)}),
ok = handle_live_rabbit(Node),
Monitors1 = case pmon:is_monitored({rabbit, Node}, Monitors) of
- true ->
- Monitors;
- false ->
- pmon:monitor({rabbit, Node}, Monitors)
- end,
+ true ->
+ Monitors;
+ false ->
+ pmon:monitor({rabbit, Node}, Monitors)
+ end,
{noreply, maybe_autoheal(State#state{monitors = Monitors1})};
handle_cast({joined_cluster, Node, NodeType}, State) ->
@@ -584,7 +584,7 @@ handle_info({mnesia_system_event,
State1 = case pmon:is_monitored({rabbit, Node}, Monitors) of
true -> State;
false -> State#state{
- monitors = pmon:monitor({rabbit, Node}, Monitors)}
+ monitors = pmon:monitor({rabbit, Node}, Monitors)}
end,
ok = handle_live_rabbit(Node),
Partitions1 = lists:usort([Node | Partitions]),
@@ -893,4 +893,4 @@ startup_log([]) ->
rabbit_log:info("Starting rabbit_node_monitor~n", []);
startup_log(Nodes) ->
rabbit_log:info("Starting rabbit_node_monitor, might be partitioned from ~p~n",
- [Nodes]).
+ [Nodes]).
diff --git a/src/rabbit_vm.erl b/src/rabbit_vm.erl
index b65536c0d4..17dae558b9 100644
--- a/src/rabbit_vm.erl
+++ b/src/rabbit_vm.erl
@@ -16,7 +16,7 @@
-module(rabbit_vm).
--export([memory/0, binary/0, ets_tables_memory/1]).
+-export([memory/0, total_memory/0, binary/0, ets_tables_memory/1]).
-define(MAGIC_PLUGINS, ["cowboy", "ranch", "sockjs"]).
@@ -30,7 +30,6 @@
%%----------------------------------------------------------------------------
-%% Like erlang:memory(), but with awareness of rabbit-y things
memory() ->
All = interesting_sups(),
{Sums, _Other} = sum_processes(
@@ -41,7 +40,7 @@ memory() ->
[aggregate(Names, Sums, memory, fun (X) -> X end)
|| Names <- distinguished_interesting_sups()],
- Mnesia = mnesia_memory(),
+ MnesiaETS = mnesia_memory(),
MsgIndexETS = ets_memory(msg_stores()),
MetricsETS = ets_memory([rabbit_metrics]),
MetricsProc =
@@ -53,8 +52,9 @@ memory() ->
0
end,
MgmtDbETS = ets_memory([rabbit_mgmt_storage]),
+ OsTotal = total_memory(),
- [{total, Total},
+ [{total, ErlangTotal},
{processes, Processes},
{ets, ETS},
{atom, Atom},
@@ -67,30 +67,137 @@ memory() ->
- ConnsReader - ConnsWriter - ConnsChannel - ConnsOther
- Qs - QsSlave - MsgIndexProc - Plugins - MgmtDbProc - MetricsProc,
- [{total, Total},
+ [
+ %% Connections
{connection_readers, ConnsReader},
{connection_writers, ConnsWriter},
{connection_channels, ConnsChannel},
{connection_other, ConnsOther},
+
+ %% Queues
{queue_procs, Qs},
{queue_slave_procs, QsSlave},
+
+ %% Processes
{plugins, Plugins},
{other_proc, lists:max([0, OtherProc])}, %% [1]
- {mnesia, Mnesia},
+
+ %% Metrics
{metrics, MetricsETS + MetricsProc},
{mgmt_db, MgmtDbETS + MgmtDbProc},
- {msg_index, MsgIndexETS + MsgIndexProc},
- {other_ets, ETS - Mnesia - MsgIndexETS - MgmtDbETS},
+
+ %% ETS
+ {mnesia, MnesiaETS},
+ {other_ets, ETS - MnesiaETS - MetricsETS - MgmtDbETS - MsgIndexETS},
+
+ %% Messages (mostly, some binaries are not messages)
{binary, Bin},
+ {msg_index, MsgIndexETS + MsgIndexProc},
+
+ %% System
{code, Code},
{atom, Atom},
- {other_system, System - ETS - Atom - Bin - Code}].
+ {other_system, System - ETS - Bin - Code - Atom + (OsTotal - ErlangTotal)},
+ {total, OsTotal}
+ ].
%% [1] - erlang:memory(processes) can be less than the sum of its
%% parts. Rather than display something nonsensical, just silence any
%% claims about negative memory. See
%% http://erlang.org/pipermail/erlang-questions/2012-September/069320.html
+%% Memory reported by erlang:memory(total) is not supposed to
+%% be equal to the total size of all pages mapped to the emulator,
+%% according to http://erlang.org/doc/man/erlang.html#memory-0
+%% erlang:memory(total) under-reports memory usage by around 20%
+-spec total_memory() -> Bytes :: integer().
+total_memory() ->
+ case get_memory_calculation_strategy() of
+ rss ->
+ case get_system_process_resident_memory() of
+ {ok, MemInBytes} ->
+ MemInBytes;
+ {error, Reason} ->
+ rabbit_log:debug("Unable to get system memory used. Reason: ~p."
+ " Falling back to erlang memory reporting",
+ [Reason]),
+ erlang:memory(total)
+ end;
+ erlang ->
+ erlang:memory(total)
+ end.
+
+-spec get_memory_calculation_strategy() -> rss | erlang.
+get_memory_calculation_strategy() ->
+ case application:get_env(rabbit, vm_memory_calculation_strategy, rss) of
+ erlang ->
+ erlang;
+ rss ->
+ rss;
+ UnsupportedValue ->
+ rabbit_log:warning(
+ "Unsupported value '~p' for vm_memory_calculation_strategy. "
+ "Supported values: (rss|erlang). "
+ "Defaulting to 'rss'",
+ [UnsupportedValue]
+ ),
+ rss
+ end.
+
+-spec get_system_process_resident_memory() -> {ok, Bytes :: integer()} | {error, term()}.
+get_system_process_resident_memory() ->
+ try
+ get_system_process_resident_memory(os:type())
+ catch _:Error ->
+ {error, {"Failed to get process resident memory", Error}}
+ end.
+
+get_system_process_resident_memory({unix,darwin}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory({unix, linux}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory({unix,freebsd}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory({unix,openbsd}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory({win32,_OSname}) ->
+ OsPid = os:getpid(),
+ Cmd = " tasklist /fi \"pid eq " ++ OsPid ++ "\" /fo LIST 2>&1 ",
+ CmdOutput = os:cmd(Cmd),
+ %% Memory usage is displayed in kilobytes
+ %% with comma-separated thousands
+ case re:run(CmdOutput, "Mem Usage:\\s+([0-9,]+)\\s+K", [{capture, all_but_first, list}]) of
+ {match, [Match]} ->
+ NoCommas = [ N || N <- Match, N =/= $, ],
+ {ok, list_to_integer(NoCommas) * 1024};
+ _ ->
+ {error, {unexpected_output_from_command, Cmd, CmdOutput}}
+ end;
+
+get_system_process_resident_memory({unix, sunos}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory({unix, aix}) ->
+ get_ps_memory();
+
+get_system_process_resident_memory(_OsType) ->
+ {error, not_implemented_for_os}.
+
+get_ps_memory() ->
+ OsPid = os:getpid(),
+ Cmd = "ps -p " ++ OsPid ++ " -o rss=",
+ CmdOutput = os:cmd(Cmd),
+ case re:run(CmdOutput, "[0-9]+", [{capture, first, list}]) of
+ {match, [Match]} ->
+ {ok, list_to_integer(Match) * 1024};
+ _ ->
+ {error, {unexpected_output_from_command, Cmd, CmdOutput}}
+ end.
+
binary() ->
All = interesting_sups(),
{Sums, Rest} =
diff --git a/src/term_to_binary_compat.erl b/src/term_to_binary_compat.erl
index a3e1045623..13396ddacb 100644
--- a/src/term_to_binary_compat.erl
+++ b/src/term_to_binary_compat.erl
@@ -18,15 +18,8 @@
-include("rabbit.hrl").
--export([queue_name_to_binary/1]).
+-export([term_to_binary_1/1]).
-queue_name_to_binary(#resource{kind = queue} = {resource, VHost, queue, Name}) ->
- VHostBSize = byte_size(VHost),
- NameBSize = byte_size(Name),
- <<131, %% Binary format "version"
- 104, 4, %% 4-element tuple
- 100, 0, 8, "resource", %% `resource` atom
- 109, VHostBSize:32, VHost/binary, %% Vhost binary
- 100, 0, 5, "queue", %% `queue` atom
- 109, NameBSize:32, Name/binary>>. %% Name binary
+term_to_binary_1(Term) ->
+ term_to_binary(Term, [{minor_version, 1}]).
diff --git a/src/vm_memory_monitor.erl b/src/vm_memory_monitor.erl
index 71e9f36c46..bc45d04d62 100644
--- a/src/vm_memory_monitor.erl
+++ b/src/vm_memory_monitor.erl
@@ -117,14 +117,14 @@ get_memory_limit() ->
get_memory_use(bytes) ->
MemoryLimit = get_memory_limit(),
- {erlang:memory(total), case MemoryLimit > 0.0 of
- true -> MemoryLimit;
- false -> infinity
- end};
+ {rabbit_vm:total_memory(), case MemoryLimit > 0.0 of
+ true -> MemoryLimit;
+ false -> infinity
+ end};
get_memory_use(ratio) ->
MemoryLimit = get_memory_limit(),
case MemoryLimit > 0.0 of
- true -> erlang:memory(total) / MemoryLimit;
+ true -> rabbit_vm:total_memory() / MemoryLimit;
false -> infinity
end.
@@ -268,7 +268,7 @@ parse_mem_limit(_) ->
internal_update(State = #state { memory_limit = MemLimit,
alarmed = Alarmed,
alarm_funs = {AlarmSet, AlarmClear} }) ->
- MemUsed = erlang:memory(total),
+ MemUsed = rabbit_vm:total_memory(),
NewAlarmed = MemUsed > MemLimit,
case {Alarmed, NewAlarmed} of
{false, true} -> emit_update_info(set, MemUsed, MemLimit),
@@ -365,6 +365,7 @@ get_total_memory({unix, aix}) ->
get_total_memory(_OsType) ->
unknown.
+
%% A line looks like "Foo bar: 123456."
parse_line_mach(Line) ->
[Name, RHS | _Rest] = string:tokens(Line, ":"),
diff --git a/test/config_schema_SUITE_data/rabbit.snippets b/test/config_schema_SUITE_data/rabbit.snippets
index 69e926100e..03a687db66 100644
--- a/test/config_schema_SUITE_data/rabbit.snippets
+++ b/test/config_schema_SUITE_data/rabbit.snippets
@@ -131,6 +131,18 @@ tcp_listen_options.exit_on_close = false",
[{vm_memory_high_watermark_paging_ratio,0.75},
{vm_memory_high_watermark,0.4}]}],
[]},
+ {memory_monitor_interval, "memory_monitor_interval = 5000",
+ [{rabbit,
+ [{memory_monitor_interval, 5000}]}],
+ []},
+ {vm_memory_calculation_strategy, "vm_memory_calculation_strategy = rss",
+ [{rabbit,
+ [{vm_memory_calculation_strategy, rss}]}],
+ []},
+ {vm_memory_calculation_strategy, "vm_memory_calculation_strategy = erlang",
+ [{rabbit,
+ [{vm_memory_calculation_strategy, erlang}]}],
+ []},
{listeners_tcp_ip,
"listeners.tcp.1 = 192.168.1.99:5672",
[{rabbit,[{tcp_listeners,[{"192.168.1.99",5672}]}]}],
diff --git a/test/partitions_SUITE.erl b/test/partitions_SUITE.erl
index 8c8a772987..b09d05b550 100644
--- a/test/partitions_SUITE.erl
+++ b/test/partitions_SUITE.erl
@@ -335,16 +335,26 @@ autoheal_unexpected_finish(Config) ->
partial_false_positive(Config) ->
[A, B, C] = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
+ suspend_node_monitor(Config, C),
block([{A, B}]),
timer:sleep(1000),
block([{A, C}]),
timer:sleep(?DELAY),
+ resume_node_monitor(Config, C),
+ timer:sleep(?DELAY),
unblock([{A, B}, {A, C}]),
timer:sleep(?DELAY),
%% When B times out A's connection, it will check with C. C will
%% not have timed out A yet, but already it can't talk to it. We
%% need to not consider this a partial partition; B and C should
%% still talk to each other.
+ %%
+ %% Because there is a chance that C can still talk to A when B
+ %% requests to check for a partial partition, we suspend C's
+ %% rabbit_node_monitor at the beginning and resume it after the
+ %% link between A and C is blocked. This way, when B asks C about
+ %% A, we make sure that the A<->C link is blocked before C's
+ %% rabbit_node_monitor processes B's request.
[B, C] = partitions(A),
[A] = partitions(B),
[A] = partitions(C),
@@ -369,7 +379,19 @@ partial_to_full(Config) ->
partial_pause_minority(Config) ->
[A, B, C] = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
set_mode(Config, pause_minority),
+ %% We suspend rabbit_node_monitor on C while we block the link
+ %% between A and B. This should make sure C's rabbit_node_monitor
+ %% processes both partial partition checks from A and B at about
+ %% the same time, and thus increase the chance both A and B decides
+ %% there is a partial partition.
+ %%
+ %% Without this, one node may see the partial partition and stop,
+ %% before the other node sees it. In this case, the other node
+ %% doesn't stop and this testcase fails.
+ suspend_node_monitor(Config, C),
block([{A, B}]),
+ timer:sleep(?DELAY),
+ resume_node_monitor(Config, C),
[await_running(N, false) || N <- [A, B]],
await_running(C, true),
unblock([{A, B}]),
@@ -394,6 +416,22 @@ set_mode(Config, Mode) ->
set_mode(Config, Nodes, Mode) ->
rabbit_ct_broker_helpers:set_partition_handling_mode(Config, Nodes, Mode).
+suspend_node_monitor(Config, Node) ->
+ rabbit_ct_broker_helpers:rpc(
+ Config, Node, ?MODULE, suspend_or_resume_node_monitor, [suspend]).
+
+resume_node_monitor(Config, Node) ->
+ rabbit_ct_broker_helpers:rpc(
+ Config, Node, ?MODULE, suspend_or_resume_node_monitor, [resume]).
+
+suspend_or_resume_node_monitor(SuspendOrResume) ->
+ Action = case SuspendOrResume of
+ suspend -> "Suspending";
+ resume -> "Resuming"
+ end,
+ rabbit_log:info("(~s) ~s node monitor~n", [?MODULE, Action]),
+ ok = sys:SuspendOrResume(rabbit_node_monitor).
+
block_unblock(Pairs) ->
block(Pairs),
timer:sleep(?DELAY),
diff --git a/test/term_to_binary_compat_prop_SUITE.erl b/test/term_to_binary_compat_prop_SUITE.erl
index d09b23c9ea..6c8a92a29f 100644
--- a/test/term_to_binary_compat_prop_SUITE.erl
+++ b/test/term_to_binary_compat_prop_SUITE.erl
@@ -24,13 +24,11 @@
-include_lib("proper/include/proper.hrl").
all() ->
- %% The test should run on OTP < 20 (erts < 9)
- case erts_gt_8() of
- true ->
- [];
- false ->
- [queue_name_to_binary]
- end.
+ [
+ pre_3_6_11_works,
+ term_to_binary_latin_atom,
+ queue_name_to_binary
+ ].
erts_gt_8() ->
Vsn = erlang:system_info(version),
@@ -47,16 +45,51 @@ end_per_suite(Config) ->
init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).
+%% If this test fails - the erlang version is not supported in
+%% RabbitMQ-3.6.10 and earlier.
+pre_3_6_11_works(Config) ->
+ Fun = fun () -> prop_pre_3_6_11_works(Config) end,
+ rabbit_ct_proper_helpers:run_proper(Fun, [], 50000).
+
+prop_pre_3_6_11_works(_Config) ->
+ ?FORALL(Term, any(),
+ begin
+ Current = term_to_binary(Term),
+ Compat = term_to_binary_compat:term_to_binary_1(Term),
+ Current =:= Compat
+ end).
+
+term_to_binary_latin_atom(Config) ->
+ Fun = fun () -> prop_term_to_binary_latin_atom(Config) end,
+ rabbit_ct_proper_helpers:run_proper(Fun, [], 10000).
+
+prop_term_to_binary_latin_atom(_Config) ->
+ ?FORALL(LatinString, list(integer(0, 255)),
+ begin
+ Length = length(LatinString),
+ Atom = list_to_atom(LatinString),
+ Binary = list_to_binary(LatinString),
+ <<131,100, Length:16, Binary/binary>> =:= term_to_binary_compat:term_to_binary_1(Atom)
+ end).
+
queue_name_to_binary(Config) ->
Fun = fun () -> prop_queue_name_to_binary(Config) end,
rabbit_ct_proper_helpers:run_proper(Fun, [], 10000).
prop_queue_name_to_binary(_Config) ->
- ?FORALL({Vhost, QName}, {binary(), binary()},
+ ?FORALL({VHost, QName}, {binary(), binary()},
begin
- Resource = rabbit_misc:r(Vhost, queue, QName),
- Legacy = term_to_binary_compat:queue_name_to_binary(Resource),
- Current = term_to_binary(Resource),
- Current =:= Legacy
- end). \ No newline at end of file
+ VHostBSize = byte_size(VHost),
+ NameBSize = byte_size(QName),
+ Expected =
+ <<131, %% Binary format "version"
+ 104, 4, %% 4-element tuple
+ 100, 0, 8, "resource", %% `resource` atom
+ 109, VHostBSize:32, VHost/binary, %% Vhost binary
+ 100, 0, 5, "queue", %% `queue` atom
+ 109, NameBSize:32, QName/binary>>, %% Name binary
+ Resource = rabbit_misc:r(VHost, queue, QName),
+ Current = term_to_binary_compat:term_to_binary_1(Resource),
+ Current =:= Expected
+ end).
diff --git a/test/topic_permission_SUITE.erl b/test/topic_permission_SUITE.erl
index 7b9d9f7701..c656746432 100644
--- a/test/topic_permission_SUITE.erl
+++ b/test/topic_permission_SUITE.erl
@@ -218,4 +218,36 @@ topic_permission_checks1(_Config) ->
Perm,
Context
) || Perm <- Permissions],
+
+ %% expand variables
+ rabbit_auth_backend_internal:set_topic_permissions(
+ <<"guest">>, <<"other-vhost">>, <<"amq.topic">>,
+ "services.{vhost}.accounts.{username}.notifications",
+ "services.{vhost}.accounts.{username}.notifications", <<"acting-user">>
+ ),
+ %% routing key OK
+ [true = rabbit_auth_backend_internal:check_topic_access(
+ User,
+ Topic#resource{virtual_host = <<"other-vhost">>},
+ Perm,
+ #{routing_key => <<"services.other-vhost.accounts.guest.notifications">>,
+ variable_map => #{
+ <<"username">> => <<"guest">>,
+ <<"vhost">> => <<"other-vhost">>
+ }
+ }
+ ) || Perm <- Permissions],
+ %% routing key KO
+ [false = rabbit_auth_backend_internal:check_topic_access(
+ User,
+ Topic#resource{virtual_host = <<"other-vhost">>},
+ Perm,
+ #{routing_key => <<"services.default.accounts.dummy.notifications">>,
+ variable_map => #{
+ <<"username">> => <<"guest">>,
+ <<"vhost">> => <<"other-vhost">>
+ }
+ }
+ ) || Perm <- Permissions],
+
ok.