-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
673 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
mod_libcluster - Join nodes into cluster | ||
======================================== | ||
|
||
Requires: | ||
- ejabberd 24.xx or higher compiled with Elixir support | ||
|
||
|
||
This small module connects this ejabberd node to other nodes | ||
using [libcluster](https://github.com/bitwalker/libcluster). | ||
|
||
Options | ||
------- | ||
|
||
This module supports several configurable options. | ||
There are some example configuration files in the `test/` directory. | ||
Options supported by this module: | ||
|
||
* `strategy` | ||
|
||
Sets the clustering strategy to use. | ||
|
||
Supported values are: | ||
- `local_epmd`: connect to all nodes managed by the local epmd program | ||
- `epmd`: connect to the nodes you specify in the `config: hosts` option | ||
- `kubernetes` | ||
|
||
Default value: `local_epmd`. | ||
|
||
* `hosts` | ||
|
||
List of erlang node names to connect. | ||
This is required, and only useful, when using the `epmd` strategy. | ||
Default value: `[]`. | ||
|
||
* `timeut` | ||
|
||
Timeout to connect to a node, expressed in milliseconds. | ||
This is only useful when using the `epmd` strategy. | ||
Default value: `infinity`. | ||
|
||
For details of options supported please check the | ||
[libcluster documentation](https://hexdocs.pm/libcluster). | ||
|
||
Test | ||
---- | ||
|
||
There's a test script in `test/test.sh` that you can run. | ||
It compiles ejabberd, installs in `/tmp/` several nodes, | ||
and builds a cluster using the desired strategy. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#modules: | ||
# 'ModLibcluster': | ||
|
||
# Connect with any other local node | ||
#strategy: local_epmd | ||
|
||
# Connect only to those specific nodes | ||
#strategy: epmd | ||
#config: | ||
# hosts: | ||
# - [email protected] | ||
# - [email protected] | ||
# - [email protected] | ||
|
||
#strategy: kubernetes | ||
#config: | ||
# mode: hostname | ||
# kubernetes_ip_lookup_mode: pods | ||
# kubernetes_namespace: "ejabberd" | ||
# kubernetes_selector: "app=ejabberd" | ||
# kubernetes_node_basename: "ejabberd" | ||
# kubernetes_service_name: "ejabberd-headless" | ||
# polling_interval: 10000 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
defmodule ModLibcluster do | ||
use Ejabberd.Module | ||
|
||
def start(_host, opts) do | ||
|
||
strategy = case opts[:strategy] do | ||
:local_epmd -> | ||
:"Elixir.Cluster.Strategy.LocalEpmd" | ||
:epmd -> | ||
:"Elixir.Cluster.Strategy.Epmd" | ||
:kubernetes -> | ||
:"Elixir.Cluster.Strategy.Kubernetes" | ||
other_strategy -> | ||
other_strategy | ||
end | ||
info("Starting ejabberd module Libcluster with stategy #{inspect(strategy)}") | ||
|
||
config = [ | ||
hosts: opts[:hosts], | ||
timeout: opts[:timeout] | ||
] | ||
info("Starting ejabberd module Libcluster with config #{inspect(config)}") | ||
|
||
topologies = [ | ||
ejabberd_cluster: [ | ||
strategy: strategy, | ||
config: config, | ||
connect: {:ejabberd_admin, :join_cluster, []}, | ||
disconnect: {:ejabberd_admin, :leave_cluster, []} | ||
] | ||
] | ||
children = [ | ||
{Cluster.Supervisor, [topologies, [name: Ejabberd.ClusterSupervisor]]}, | ||
] | ||
Supervisor.start_link(children, strategy: :one_for_one, name: Ejabberd.Supervisor) | ||
info("Started ejabberd module Libcluster Demo") | ||
:ok | ||
end | ||
|
||
def stop(_host) do | ||
info("Stopping ejabberd module Libcluster Demo") | ||
:ok | ||
end | ||
|
||
def depends(_host, _opts) do | ||
[] | ||
end | ||
|
||
def mod_opt_type(:hosts) do | ||
:econf.list(:econf.atom) | ||
end | ||
|
||
def mod_opt_type(:strategy) do | ||
:econf.atom | ||
end | ||
|
||
def mod_opt_type(:timeout) do | ||
:econf.either(:infinity, :econf.int()); | ||
end | ||
|
||
def mod_options(_host) do | ||
[ | ||
{:hosts, []}, | ||
{:strategy, :local_epmd}, | ||
{:timeout, :infinity} | ||
] | ||
end | ||
|
||
def mod_doc() do | ||
%{:desc => "This is just an empty string."} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
author: "Badlop <badlop at process-one.net>" | ||
category: "cluster" | ||
summary: "Join nodes into cluster" | ||
home: "https://github.com/processone/ejabberd-contrib/tree/master/" | ||
url: "[email protected]:processone/ejabberd-contrib.git" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{deps, [ | ||
{jason, "1.5.0-alpha.2", {git, "https://github.com/michalmuskala/jason", {branch, "master"}}}, | ||
{libcluster, "3.3.3", {git, "https://github.com/bitwalker/libcluster", {branch, "main"}}} | ||
]}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
modules: | ||
'ModLibcluster': | ||
# Connect only to those specific nodes | ||
strategy: epmd | ||
timeout: 5000 | ||
hosts: | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
modules: | ||
'ModLibcluster': | ||
# Connect with any other local node | ||
strategy: local_epmd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#!/bin/bash | ||
|
||
COLOUR="\e[1;49;33m" | ||
NEUTRAL="\033[00m" | ||
|
||
log() { | ||
echo "" | ||
echo -e $COLOUR"==> $1"$NEUTRAL | ||
} | ||
|
||
MOD=$(pwd) | ||
|
||
TOOL=$1 | ||
STR=$2 | ||
SRC=$3 | ||
if [ -n "$TOOL" ] && [ -n "$STR" ] && [ -n "$SRC" ] ; then | ||
log "Using tool: $TOOL" | ||
log "Using strategy: $STR" | ||
log "Using ejabberd source code from: $SRC" | ||
else | ||
echo "Usage: $0 <tool> <strategy> <path>" | ||
echo " <tool> = mix | rebar3" | ||
echo " <strategy> = local_epmd | epmd" | ||
echo " <path> = path to the ejabberd source code" | ||
echo "For example: $0 mix local_epmd /home/user1/git/ejabberd/" | ||
exit 1 | ||
fi | ||
|
||
cd "$SRC" || exit 1 | ||
|
||
log "Compile ejabberd release..." | ||
|
||
compile() { | ||
./autogen.sh | ||
./configure \ | ||
--with-rebar=$TOOL \ | ||
--enable-all | ||
make | ||
rm _build/prod/*.tar.gz | ||
make rel | ||
} | ||
|
||
compile | ||
|
||
log "Preparing ejabberd nodes..." | ||
|
||
case "$TOOL" in | ||
mix) | ||
echo "Setting up 'mix' tool..." | ||
FILE=$(ls -1 _build/prod/*.tar.gz) | ||
;; | ||
rebar3) | ||
echo "Setting up 'rebar3' tool..." | ||
FILE=$(ls -1 _build/prod/rel/ejabberd/*.tar.gz) | ||
;; | ||
esac | ||
|
||
create_node() { | ||
N=$1 | ||
log "Preparing node $N using file $FILE..." | ||
rm -rf /tmp/libcluster/"$N" | ||
mkdir -p /tmp/libcluster/"$N" | ||
tar -xzf "$FILE" -C /tmp/libcluster/"$N" | ||
sed -i "s|#' POLL|EJABBERD_BYPASS_WARNINGS=true\n\n#' POLL|g" /tmp/libcluster/"$N"/conf/ejabberdctl.cfg | ||
sed -i "s|#ERLANG_NODE=.*|ERLANG_NODE=ejabberd$N@127.0.0.1|" /tmp/libcluster/"$N"/conf/ejabberdctl.cfg | ||
sed -i "s| port: \([0-9]*\)| port: \1$N|g" /tmp/libcluster/"$N"/conf/ejabberd.yml | ||
sed -i "s|mod_proxy65:|mod_proxy65:\n port: 777$N|" /tmp/libcluster/"$N"/conf/ejabberd.yml | ||
node[N]=/tmp/libcluster/"$N"/bin/ejabberdctl | ||
} | ||
|
||
create_node 1 | ||
create_node 2 | ||
create_node 3 | ||
|
||
FIRST=${node[1]} | ||
SECOND=${node[2]} | ||
THIRD=${node[3]} | ||
|
||
log "Let's start the first node..." | ||
|
||
echo "first: $FIRST" | ||
$FIRST start | ||
$FIRST started | ||
$FIRST set_master self | ||
|
||
log "Uninstall and install mod_libcluster:" | ||
|
||
$FIRST module_uninstall mod_libcluster | ||
rm -rf $MOD/deps/ | ||
rm -rf $MOD/ebin/ | ||
$FIRST module_install mod_libcluster || exit 1 | ||
|
||
log "Configure mod_libcluster:" | ||
|
||
case "$STR" in | ||
local_epmd) | ||
echo "Setting up 'local_epmd' config..." | ||
cp "$MOD"/test/local_epmd.yml \ | ||
"$HOME"/.ejabberd-modules/mod_libcluster/conf/mod_libcluster.yml | ||
;; | ||
epmd) | ||
echo "Setting up 'epmd' config..." | ||
cp "$MOD"/test/epmd.yml \ | ||
"$HOME"/.ejabberd-modules/mod_libcluster/conf/mod_libcluster.yml | ||
;; | ||
esac | ||
|
||
log "Initial cluster of first node (should be just this node):" | ||
|
||
$FIRST list_cluster | ||
|
||
log "Let's start the second node, it should connect automatically to the first node..." | ||
|
||
$SECOND start | ||
$SECOND started | ||
sleep 5 # wait a few seconds to let the second node join the cluster properly | ||
$SECOND set_master [email protected] | ||
|
||
log "Let's start the third node, it should connect automatically to the first node..." | ||
|
||
$THIRD start | ||
$THIRD started | ||
sleep 5 # wait a few seconds to let the second node join the cluster properly | ||
|
||
log "Cluster as seen by first node:" | ||
|
||
$FIRST list_cluster | ||
|
||
log "Cluster as seen by second node:" | ||
|
||
$SECOND list_cluster | ||
|
||
log "Cluster as seen by third node:" | ||
|
||
$THIRD list_cluster | ||
|
||
log "Stop first node, and check cluster as seen by second node:" | ||
|
||
$FIRST stop | ||
$FIRST stopped | ||
$SECOND list_cluster | ||
|
||
log "... as seen by third node:" | ||
|
||
$THIRD list_cluster | ||
|
||
log "Start again first node, and check cluster as seen by all the nodes:" | ||
|
||
$FIRST start | ||
$FIRST started | ||
sleep 5 | ||
echo "First: " | ||
$FIRST list_cluster | ||
echo "Second: " | ||
$SECOND list_cluster | ||
echo "Third: " | ||
$THIRD list_cluster | ||
|
||
log "Stopping all nodes..." | ||
|
||
$FIRST stop | ||
$SECOND stop | ||
$THIRD stop |