2016-06-20 23:52:36 +08:00
|
|
|
## 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.
|
|
|
|
|
|
|
|
|
|
|
|
defmodule RabbitMQ.CLI.Plugins.Helpers do
|
2016-06-22 22:32:49 +08:00
|
|
|
import RabbitCommon.Records
|
|
|
|
|
2016-06-20 23:52:36 +08:00
|
|
|
def list(opts) do
|
2016-06-22 01:11:46 +08:00
|
|
|
{:ok, dir} = plugins_dir(opts)
|
2016-06-20 23:52:36 +08:00
|
|
|
add_all_to_path(dir)
|
2016-08-11 06:27:13 +08:00
|
|
|
:lists.usort(:rabbit_plugins.list(to_char_list(dir)))
|
2016-06-20 23:52:36 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def read_enabled(opts) do
|
|
|
|
{:ok, enabled} = enabled_plugins_file(opts)
|
2016-06-22 01:11:46 +08:00
|
|
|
:rabbit_plugins.read_enabled(to_char_list(enabled))
|
2016-06-20 23:52:36 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def enabled_plugins_file(opts) do
|
|
|
|
case opts[:enabled_plugins_file] || System.get_env("RABBITMQ_ENABLED_PLUGINS_FILE") do
|
|
|
|
nil -> {:error, :no_plugins_file};
|
|
|
|
file ->
|
|
|
|
case File.exists?(file) do
|
|
|
|
true -> {:ok, file};
|
2016-07-11 00:47:27 +08:00
|
|
|
false -> {:error, :enabled_plugins_file_does_not_exist}
|
2016-06-20 23:52:36 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-22 01:11:46 +08:00
|
|
|
def plugins_dir(opts) do
|
|
|
|
case opts[:plugins_dir] || System.get_env("RABBITMQ_PLUGINS_DIR") do
|
2016-06-20 23:52:36 +08:00
|
|
|
nil -> {:error, :no_plugins_dir};
|
|
|
|
dir ->
|
|
|
|
case File.dir?(dir) do
|
|
|
|
true -> {:ok, dir};
|
2016-07-11 00:47:27 +08:00
|
|
|
false -> {:error, :plugins_dir_does_not_exist}
|
2016-06-20 23:52:36 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def require_rabbit(opts) do
|
|
|
|
home = opts[:rabbitmq_home] || System.get_env("RABBITMQ_HOME")
|
2016-06-22 01:11:46 +08:00
|
|
|
case home do
|
|
|
|
nil ->
|
2016-07-11 02:36:12 +08:00
|
|
|
{:error, {:unable_to_load_rabbit, :rabbitmq_home_is_undefined}};
|
2016-06-22 01:11:46 +08:00
|
|
|
_ ->
|
|
|
|
path = Path.join(home, "ebin")
|
|
|
|
Code.append_path(path)
|
|
|
|
case Application.load(:rabbit) do
|
2016-06-22 22:32:49 +08:00
|
|
|
:ok ->
|
|
|
|
Code.ensure_loaded(:rabbit_plugins)
|
|
|
|
:ok;
|
|
|
|
{:error, {:already_loaded, :rabbit}} ->
|
|
|
|
Code.ensure_loaded(:rabbit_plugins)
|
|
|
|
:ok;
|
|
|
|
{:error, err} ->
|
|
|
|
{:error, {:unable_to_load_rabbit, err}}
|
2016-06-22 01:11:46 +08:00
|
|
|
end
|
2016-06-20 23:52:36 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-21 20:54:18 +08:00
|
|
|
def set_enabled_plugins(plugins, mode, node_name, opts) do
|
2016-08-11 06:27:13 +08:00
|
|
|
plugin_atoms = :lists.usort(for plugin <- plugins, do: to_atom(plugin))
|
2016-06-22 22:32:49 +08:00
|
|
|
require_rabbit(opts)
|
2016-06-21 20:54:18 +08:00
|
|
|
{:ok, plugins_file} = enabled_plugins_file(opts)
|
2016-06-23 01:00:21 +08:00
|
|
|
case write_enabled_plugins(plugin_atoms, plugins_file, opts) do
|
2016-06-21 20:54:18 +08:00
|
|
|
{:ok, enabled_plugins} ->
|
|
|
|
case mode do
|
|
|
|
:online ->
|
|
|
|
case update_enabled_plugins(node_name, plugins_file) do
|
|
|
|
{:ok, started, stopped} ->
|
2016-06-23 01:00:21 +08:00
|
|
|
%{mode: :online,
|
|
|
|
started: Enum.sort(started),
|
|
|
|
stopped: Enum.sort(stopped),
|
|
|
|
enabled: Enum.sort(enabled_plugins)};
|
2016-06-21 20:54:18 +08:00
|
|
|
{:error, :offline} ->
|
2016-06-23 01:00:21 +08:00
|
|
|
%{mode: :offline, enabled: Enum.sort(enabled_plugins)};
|
2016-06-21 20:54:18 +08:00
|
|
|
{:error, {:enabled_plugins_mismatch, _, _}} = err ->
|
|
|
|
err
|
|
|
|
end;
|
|
|
|
:offline ->
|
2016-06-23 01:00:21 +08:00
|
|
|
%{mode: :offline, enabled: Enum.sort(enabled_plugins)}
|
2016-06-21 20:54:18 +08:00
|
|
|
end;
|
|
|
|
{:error, _} = err -> err
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-23 01:00:21 +08:00
|
|
|
defp to_atom(str) when is_binary(str) do
|
|
|
|
String.to_atom(str)
|
|
|
|
end
|
|
|
|
defp to_atom(lst) when is_list(lst) do
|
|
|
|
List.to_atom(lst)
|
|
|
|
end
|
|
|
|
defp to_atom(atm) when is_atom(atm) do
|
|
|
|
atm
|
|
|
|
end
|
|
|
|
|
2016-06-21 20:54:18 +08:00
|
|
|
defp write_enabled_plugins(plugins, plugins_file, opts) do
|
2016-08-11 06:27:13 +08:00
|
|
|
all = list(opts)
|
2016-06-22 22:32:49 +08:00
|
|
|
all_plugin_names = for plugin(name: name) <- all, do: name
|
2016-08-11 06:27:13 +08:00
|
|
|
|
|
|
|
case MapSet.difference(MapSet.new(plugins), MapSet.new(all_plugin_names)) do
|
|
|
|
%MapSet{} ->
|
2016-06-22 01:11:46 +08:00
|
|
|
case :rabbit_file.write_term_file(to_char_list(plugins_file), [plugins]) do
|
2016-06-21 20:54:18 +08:00
|
|
|
:ok ->
|
|
|
|
{:ok, :rabbit_plugins.dependencies(false, plugins, all)};
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, {:cannot_write_enabled_plugins_file, plugins_file, reason}}
|
|
|
|
end;
|
|
|
|
missing ->
|
|
|
|
{:error, {:plugins_not_found, missing}}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defp update_enabled_plugins(node_name, plugins_file) do
|
|
|
|
case :rabbit_misc.rpc_call(node_name, :rabbit_plugins,
|
|
|
|
:ensure, [plugins_file]) do
|
|
|
|
{:badrpc, :nodedown} -> {:error, :offline};
|
|
|
|
{:ok, start, stop} -> {:ok, start, stop};
|
|
|
|
{:error, _} = err -> err
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-20 23:52:36 +08:00
|
|
|
defp add_all_to_path(dir) do
|
|
|
|
{:ok, subdirs} = File.ls(dir)
|
|
|
|
for subdir <- subdirs do
|
|
|
|
Path.join([dir, subdir, "ebin"])
|
|
|
|
|> Code.append_path
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|