Cassandra role
In first place I added a variable with the Cassandra ring size as a max_nodes to its role.- {role: cassandra, max_nodes: 13}
This value is used to create a Ansible local fact. To learn more on local facts please read this Curtis Collicutt article, which is the best for my script. Please note that the following code is a Jinja template not ready script.
#!/bin/sh
NODE=$(hostname |grep -o -P "\d+")
TOKEN=$(echo '2^127/{{ max_nodes }}' | bc)
cat <
{
"node_number": $NODE,
"token": $TOKEN
}
EOF
The above script print onto standard output a json with two variables.
- node_number - is created based on hostname. The number a hostname correspond to a ring position (i.e. cassandra-4 is forth node).
- token - is 'a main part' of token value calculation. The rest is done in Cassandra configuration template:
That's sounds complicated and it is. As often there is a historical explanation to that situation. Initially, the whole calculation was done in the template. It worked for 16 node ring, but not for 15. It didn't work, because division two integral number (2**127/15) results in float one in jinja what lead to rounding error!
Ansible commands
As a bonus two example of using Ansible to run a bit more complicated command on many hosts.- Reads token position from configuration file and initialize node move in a screen session. Please note escape character in front of '$'.
ansible \
-i inventory/ec.py \
-m shell \
-a "screen -d -m \
nodetool -h localhost move \
\$(awk '/initial_token/ {print \$2}' \
/etc/cassandra/default.conf/cassandra.yaml)"\
tag_pool_cassandra
- Much simpler. Checks that screen runs. AFAIK you have to use shell module if you want to use UNIX pipe.
ansible \
-i inventory/ec2.py \
-m shell \
-a "ps -ef| grep SCREEN"\
tag_pool_cassandra