1%% This Source Code Form is subject to the terms of the Mozilla Public
2%% License, v. 2.0. If a copy of the MPL was not distributed with this
3%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4%%
5%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates.  All rights reserved.
6%%
7
8-module(rabbit_queue_location_validator).
9-behaviour(rabbit_policy_validator).
10
11-include_lib("rabbit_common/include/rabbit.hrl").
12-include("amqqueue.hrl").
13
14-export([validate_policy/1, validate_strategy/1]).
15
16-rabbit_boot_step({?MODULE,
17                   [{description, "Queue location policy validation"},
18                    {mfa, {rabbit_registry, register,
19                           [policy_validator,
20                            <<"queue-master-locator">>,
21                            ?MODULE]}},
22		    {requires, rabbit_registry},
23		    {enables, recovery}]}).
24
25validate_policy(KeyList) ->
26    case proplists:lookup(<<"queue-master-locator">> , KeyList) of
27        {_, Strategy} -> case validate_strategy(Strategy) of
28                             {error, _, _} = Er -> Er;
29                             _ -> ok
30                         end;
31        _             -> {error, "queue-master-locator undefined"}
32    end.
33
34validate_strategy(Strategy) ->
35    case module(Strategy) of
36        R = {ok, _M} -> R;
37        _            ->
38            {error, "~p invalid queue-master-locator value", [Strategy]}
39    end.
40
41policy(Policy, Q) ->
42    case rabbit_policy:get(Policy, Q) of
43        undefined -> none;
44        P         -> P
45    end.
46
47module(Q) when ?is_amqqueue(Q) ->
48    case policy(<<"queue-master-locator">>, Q) of
49        undefined -> no_location_strategy;
50        Mode      -> module(Mode)
51    end;
52module(Strategy) when is_binary(Strategy) ->
53    case rabbit_registry:binary_to_type(Strategy) of
54        {error, not_found} -> no_location_strategy;
55        T ->
56            case rabbit_registry:lookup_module(queue_master_locator, T) of
57                {ok, Module} ->
58                    case code:which(Module) of
59                        non_existing -> no_location_strategy;
60                        _            -> {ok, Module}
61                    end;
62                _            ->
63                    no_location_strategy
64            end
65    end;
66module(Strategy) ->
67    module(rabbit_data_coercion:to_binary(Strategy)).
68