├── .gitignore ├── files ├── sysctl │ └── 50-cassandra.conf ├── systemd │ └── cassandra.service ├── cassandra │ └── cassandra_config └── bash_completion │ └── nodetool ├── LICENSE ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md └── cassandra.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Packer 2 | builds/cache/* 3 | builds/providers/* 4 | builds/sandbox/* 5 | !.gitkeep 6 | 7 | # macOS 8 | *.DS_Store 9 | .AppleDouble 10 | .LSOverride 11 | ._* 12 | 13 | # Linux 14 | *~ 15 | 16 | # Windows 17 | Desktop.ini 18 | Thumbs.db 19 | 20 | -------------------------------------------------------------------------------- /files/sysctl/50-cassandra.conf: -------------------------------------------------------------------------------- 1 | fs.file-max = 524288 2 | kernel.pid_max = 262144 3 | kernel.shmmax = 4294967296 4 | net.core.netdev_max_backlog = 16384 5 | net.core.optmem_max = 25165824 6 | net.core.rmem_default = 25165824 7 | net.core.rmem_max = 25165824 8 | net.core.somaxconn = 8192 9 | net.core.wmem_default = 131072 10 | net.core.wmem_max = 25165824 11 | net.ipv4.ip_local_port_range = 10000 65535 12 | net.ipv4.tcp_ecn = 0 13 | net.ipv4.tcp_fin_timeout = 5 14 | net.ipv4.tcp_keepalive_intvl = 3 15 | net.ipv4.tcp_keepalive_probes = 3 16 | net.ipv4.tcp_keepalive_time = 120 17 | net.ipv4.tcp_max_syn_backlog = 8192 18 | net.ipv4.tcp_rmem = 4096 87380 16777216 19 | net.ipv4.tcp_syn_retries = 2 20 | net.ipv4.tcp_synack_retries = 2 21 | net.ipv4.tcp_tw_recycle = 1 22 | #net.ipv4.tcp_tw_reuse = 1 23 | net.ipv4.tcp_window_scaling = 1 24 | net.ipv4.tcp_wmem = 4096 65536 16777216 25 | vm.max_map_count = 2097150 26 | vm.swappiness = 5 27 | -------------------------------------------------------------------------------- /files/systemd/cassandra.service: -------------------------------------------------------------------------------- 1 | # 2 | # Systemd script to manage a Cassandra node. 3 | # 4 | # Copyright 2016-2022, Frederico Martins 5 | # Author: Frederico Martins 6 | # 7 | # SPDX-License-Identifier: MIT 8 | # 9 | 10 | [Unit] 11 | Description=Cassandra 12 | After=network.target network-online.target 13 | Wants=network-online.target 14 | 15 | [Service] 16 | Type=forking 17 | User=cassandra 18 | Group=cassandra 19 | PIDFile=/var/run/cassandra/cassandra.pid 20 | WorkingDirectory=/srv/cassandra 21 | PermissionsStartOnly=true 22 | ExecStartPre=-/usr/bin/install -o cassandra -g cassandra -d /var/run/cassandra 23 | ExecStart=/srv/cassandra/bin/cassandra -p /var/run/cassandra/cassandra.pid 24 | SyslogIdentifier=cassandra 25 | StandardOutput=journal 26 | StandardError=journal 27 | LimitNOFILE=infinity 28 | LimitMEMLOCK=infinity 29 | LimitNPROC=infinity 30 | LimitAS=infinity 31 | SuccessExitStatus=143 32 | Restart=always 33 | RestartSec=20 34 | 35 | [Install] 36 | WantedBy=multi-user.target 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2022, Frederico Martins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | [author]: # (Frederico Martins ) 2 | [version]: # (1.0) 3 | [license]: # (SPDX-License-Identifier: CC-BY-4.0) 4 | [copyright]: # (2016-2022, Frederico Martins) 5 | 6 | This project follows a No Code of Conduct (NCoC) philosophy. We are all human 7 | beings. We should all be capable of getting along well. 8 | 9 | # Contributor (No) Code of Conduct 10 | 11 | Everyone is expected to behave like an adult and therefore be capable of 12 | having adult discussions. Everyone contributions are accepted regardless of 13 | their level of experience, gender, gender identity and expression, sexual 14 | orientation, disability, personal appearance, body size, race, ethnicity, age, 15 | religion, or nationality. The owners or copyright holders of this project are 16 | not members of a support group for human emotion. This is a community that 17 | strives to focus around its topics. Anything else takes away from that. 18 | 19 | Everyone should be able to freely express their ideas without being offended 20 | by nor offend others. 21 | 22 | PROBLEMS, OR OTHER SITUATIONS, SHOULD BE ADDRESSED LIKE IN ANY OTHER PLATFORM, 23 | PROJECT OR DISCUSSION FORUM. IN NO EVENT SHALL THE OWNERS OR COPYRIGHT HOLDERS 24 | OF THIS PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25 | IN AN ACTION, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 26 | THIS PROJECT COMMUNITY. 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you are thinking of contributing code to this project, first of all, thank 4 | you! All fixes, patches and enhancements to it are very warmly welcomed. 5 | 6 | Please take a moment to review this document in order to find how your 7 | contribution can be possible. 8 | 9 | ## Bugs and Feature Requests 10 | 11 | The preferred way to report bugs or request features is to use 12 | [GitHub issues](issues). For this project, however, that feature is not 13 | available. 14 | 15 | ## Pull Requests 16 | 17 | 1. Create a [GitHub account](https://github.com/join) (if you don't have one already) 18 | 2. [Fork](https://help.github.com/articles/fork-a-repo) this project 19 | 3. Create your feature branch: `git checkout -b my-new-feature` 20 | 4. Make your changes 21 | 5. Commit your changes: `git commit -am 'Add some feature'` 22 | 6. Push to the branch: `git push origin my-new-feature` 23 | 7. Submit a pull request 24 | 25 | Before you submit a 26 | [pull request](https://help.github.com/articles/using-pull-requests/) from your 27 | forked repo, check that it meets these guidelines: 28 | 29 | - If the pull request adds or changes a functionality, make sure the 30 | documentation is also created or updated as part of the same pull request. 31 | - Try not to put more than one feature or bug fix in a single pull request. Create a 32 | separate pull request for each feature or bug fix. 33 | - Squash your commits into one for each pull request: `git reset --soft HEAD~ && git commit`. 34 | 35 | ## License 36 | 37 | By contributing to this project, you agree that your contributions will be licensed under its [LICENSE](LICENSE). 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apache Cassandra AMI 2 | 3 | AMI that should be used to create virtual machines with Apache Cassandra 4 | installed. 5 | 6 | ## Synopsis 7 | 8 | This script will create an AMI with Apache Cassandra installed and with all of 9 | the required initialization scripts. 10 | 11 | The AMI resulting from this script should be the one used to instantiate a 12 | Cassandra server (standalone or cluster). 13 | 14 | ## Getting Started 15 | 16 | There are a couple of things needed for the script to work. 17 | 18 | ### Prerequisites 19 | 20 | Packer and AWS Command Line Interface tools need to be installed on your local 21 | computer. 22 | To build a base image you have to know the id of the latest Debian AMI files 23 | for the region where you wish to build the AMI. 24 | 25 | #### Packer 26 | 27 | Packer installation instructions can be found 28 | [here](https://www.packer.io/docs/installation.html). 29 | 30 | #### AWS Command Line Interface 31 | 32 | AWS Command Line Interface installation instructions can be found [here](http://docs.aws.amazon.com/cli/latest/userguide/installing.html) 33 | 34 | #### Debian AMI's 35 | 36 | This AMI will be based on an official Debian AMI. The latest version of that 37 | AMI will be used. 38 | 39 | A list of all the Debian AMI id's can be found at the Debian official page: 40 | [Debian official Amazon EC2 Images](https://wiki.debian.org/Cloud/AmazonEC2Image/) 41 | 42 | ### Usage 43 | 44 | In order to create the AMI using this packer template you need to provide a 45 | few options. 46 | 47 | ``` 48 | Usage: 49 | packer build \ 50 | -var 'aws_access_key=AWS_ACCESS_KEY' \ 51 | -var 'aws_secret_key=' \ 52 | -var 'aws_region=' \ 53 | -var 'cassandra_version=' \ 54 | [-var 'option=value'] \ 55 | cassandra.json 56 | ``` 57 | #### Script Options 58 | 59 | - `aws_access_key` - *[required]* The AWS access key. 60 | - `aws_ami_name` - The AMI name (default value: "cassandra"). 61 | - `aws_ami_name_prefix` - Prefix for the AMI name (default value: ""). 62 | - `aws_instance_type` - The instance type to use for the build (default value: "t2.micro"). 63 | - `aws_region` - *[required]* The regions were the build will be performed. 64 | - `aws_secret_key` - *[required]* The AWS secret key. 65 | - `cassandra_version` - *[required]* Cassandra version. 66 | - `java_build_number` - Java build number (default value: "11"). 67 | - `java_major_version` - Java major version (default value: "8"). 68 | - `java_token` - Java link token (default version: "d54c1d3a095b4ff2b6607d096fa80163"). 69 | - `java_update_version` - Java update version (default value: "131"). 70 | - `system_locale` - Locale for the system (default value: "en_US"). 71 | 72 | ### Instantiate a Cluster 73 | 74 | In order to end up with a functional Cassandra Cluster some configurations have 75 | to be performed after instantiating the servers. 76 | 77 | To help perform those configurations a small script is included on the AWS 78 | image. The script is called **cassandra_config**. 79 | 80 | #### Configuration Script 81 | 82 | The script can and should be used to set some of the Cassandra options as well 83 | as setting the Cassandra service to start at boot. 84 | 85 | ``` 86 | Usage: cassandra_config [options] 87 | ``` 88 | 89 | ##### Options 90 | 91 | * `-a` - Sets the auto_bootstrap option to 'on'. 92 | * `-c ` - Sets the cluster_name option to the value given (default value is 'Cassandra Cluster'). 93 | * `-D` - Disables the Cassandra service from start at boot time. 94 | * `-E` - Enables the Cassandra service to start at boot time. 95 | * `-i
` - Sets the cassandra listen address (default value is '127.0.0.1'). 96 | * `-m ` - Sets Cassandra maximum heap size. Values should be provided following the same Java heap nomenclature. 97 | * `-n ` - Sets Cassandra heap new size. Values should be provided following the same Java heap nomenclature. 98 | * `-r` - Sets the endpoint_snitch option to 'EC2MultiRegionSnitch' (default value is 'SimpleSnitch'). 99 | * `-s
` - Sets the address of one seed node (or several seed nodes if the addressess are separated with a comma). 100 | * `-S` - Starts the Cassandra service after performing the required configurations (if any given). 101 | * `-t ` - Sets the number of tokens (default value is '4'). 102 | * `-W ` - Waits the specified amount of seconds before starting the Cassandra service (default value is '0'). 103 | 104 | #### Configuring a Cassandra Node 105 | 106 | To prepare an instance to act as a Cassandra cluster node the following steps 107 | need to be performed. 108 | 109 | Run the configuration tool (*cassandra_config*) to configure the instance. 110 | 111 | ``` 112 | cassandra_config -E -S 113 | ``` 114 | 115 | After this steps a Cassandra node (for a single node cluster) should be running 116 | and configured to start on server boot. 117 | 118 | For a cluster with more than one Cassandra node other options have to be 119 | configured on each instance using the same configuration tool 120 | (*cassandra_config*). 121 | 122 | ``` 123 | cassandra_config -c 'My Cluster' -E -i 10.0.0.1 -s 10.0.0.1 -s 10.0.0.2,10.0.0.3 -S 124 | ``` 125 | 126 | After this steps, the first node of the Cassandra cluster (for a three node 127 | cluster) should be running and configured to start on server boot. 128 | 129 | More options can be used on the instance configuration, see the 130 | [Configuration Script](#configuration-script) section for more details 131 | 132 | ## Services 133 | 134 | This AMI will have the SSH service running as well as the Cassandra services. 135 | The following ports will have to be configured on Security Groups. 136 | 137 | | Service | Port | Protocol | 138 | |------------------------------------|:------:|:--------:| 139 | | SSH | 22 | TCP | 140 | | Cassandra Inter-Node Cluster | 7000 | TCP | 141 | | Cassandra SSL inter-node cluster | 7001 | TCP | 142 | | JMX Monitoring | 7199 | TCP | 143 | | Cassandra CQL Native Transport | 9042 | TCP | 144 | | Cassandra SSL CQL Native Transport | 9142 | TCP | 145 | | Cassandra Thrift | 9160 | TCP | 146 | 147 | More details can be found 148 | [here](http://docs.datastax.com/en/cassandra/3.x/cassandra/configuration/secureFireWall.html?hl=firewall). 149 | 150 | ## Contributing 151 | 152 | 1. Fork it! 153 | 2. Create your feature branch: `git checkout -b my-new-feature` 154 | 3. Commit your changes: `git commit -am 'Add some feature'` 155 | 4. Push to the branch: `git push origin my-new-feature` 156 | 5. Submit a pull request 157 | 158 | Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file for more details on how 159 | to contribute to this project. 160 | 161 | ## Versioning 162 | 163 | This project uses [SemVer](http://semver.org/) for versioning. For the versions 164 | available, see the [tags on this repository](https://github.com/fscm/packer-aws-cassandra/tags). 165 | 166 | ## Authors 167 | 168 | * **Frederico Martins** - [fscm](https://github.com/fscm) 169 | 170 | See also the list of [contributors](https://github.com/fscm/packer-aws-cassandra/contributors) 171 | who participated in this project. 172 | 173 | ## License 174 | 175 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) 176 | file for details 177 | -------------------------------------------------------------------------------- /files/cassandra/cassandra_config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Shell script to configure some options of Cassandra. 4 | # 5 | # Copyright 2016-2022, Frederico Martins 6 | # Author: Frederico Martins 7 | # 8 | # SPDX-License-Identifier: MIT 9 | # 10 | # This program is free software. You can use it and/or modify it under the 11 | # terms of the MIT License. 12 | # 13 | 14 | set -e 15 | 16 | BASEDIR=$(dirname $0) 17 | BASENAME=$(basename $0) 18 | __TS__=$(date +%Y%m%d%H%M%S) 19 | 20 | # Configuration files 21 | CASSANDRA_ENV="/srv/cassandra/conf/cassandra-env.sh" 22 | CASSANDRA_YAML="/srv/cassandra/conf/cassandra.yaml" 23 | 24 | # Variables 25 | CASSANDRA_DISABLE=0 26 | CASSANDRA_ENABLE=0 27 | CASSANDRA_START=0 28 | CASSANDRA_WAIT=0 29 | 30 | CASSANDRA_BOOTSTRAP=0 31 | CASSANDRA_CLUSTER_NAME= 32 | CASSANDRA_HEAP_MAXSIZE= 33 | CASSANDRA_HEAP_NEWSIZE= 34 | CASSANDRA_IP_ADDRESS= 35 | CASSANDRA_MULTIREGION=0 36 | CASSANDRA_SEEDS= 37 | CASSANDRA_TOKENS= 38 | 39 | __TMP_SEEDS__=() 40 | 41 | # Usage 42 | function show_usage() { 43 | echo "Usage: ${BASENAME} [options]" 44 | echo " options:" 45 | echo " -a Sets the auto_bootstrap option to 'on'." 46 | echo " -c Sets the cluster_name option to the value given (default" 47 | echo " value is 'Cassandra Cluster')." 48 | echo " -D Disables the Cassandra service from start at boot time." 49 | echo " -E Enables the Cassandra service to start at boot time." 50 | echo " -i
Sets the cassandra listen address (default value is" 51 | echo " '127.0.0.1')." 52 | echo " -m Sets Cassandra maximum heap size. Values should be provided" 53 | echo " following the same Java heap nomenclature." 54 | echo " -n Sets Cassandra heap new size. Values should be provided" 55 | echo " following the same Java heap nomenclature." 56 | echo " -r Sets the endpoint_snitch option to 'EC2MultiRegionSnitch'" 57 | echo " (default value is 'SimpleSnitch')." 58 | echo " -s
Sets the address of one seed node (or several seed nodes if" 59 | echo " the addressess are separated with a comma)." 60 | echo " -S Starts the Cassandra service after performing the required" 61 | echo " configurations (if any given)." 62 | echo " -t Sets the number of tokens (default value is '4')." 63 | echo " -W Waits the specified amount of seconds before starting the" 64 | echo " Cassandra service (default value is '0')." 65 | } 66 | 67 | # Options parsing 68 | while getopts ":ac:DEi:m:n:rs:St:W:" opt; do 69 | case $opt in 70 | a) 71 | CASSANDRA_BOOTSTRAP=1 72 | ;; 73 | c) 74 | CASSANDRA_CLUSTER_NAME=${OPTARG} 75 | ;; 76 | D) 77 | CASSANDRA_DISABLE=1 78 | ;; 79 | E) 80 | CASSANDRA_ENABLE=1 81 | ;; 82 | i) 83 | CASSANDRA_IP_ADDRESS=${OPTARG} 84 | ;; 85 | m) 86 | CASSANDRA_HEAP_MAXSIZE=${OPTARG} 87 | ;; 88 | n) 89 | CASSANDRA_HEAP_NEWSIZE=${OPTARG} 90 | ;; 91 | r) 92 | CASSANDRA_MULTIREGION=1 93 | ;; 94 | s) 95 | __TMP_SEEDS__+=("${OPTARG}") 96 | ;; 97 | S) 98 | CASSANDRA_START=1 99 | ;; 100 | t) 101 | CASSANDRA_TOKENS=${OPTARG} 102 | ;; 103 | W) 104 | CASSANDRA_WAIT=${OPTARG} 105 | ;; 106 | \?) 107 | echo >&2 " [ERROR] Invalid option: -${OPTARG}" 108 | exit 1 109 | ;; 110 | :) 111 | echo >&2 " [ERROR] Option -${OPTARG} requires an argument" 112 | exit 2 113 | ;; 114 | esac 115 | done 116 | 117 | # Check arguments 118 | if [[ $# -eq 0 ]]; then 119 | show_usage 120 | exit 3 121 | fi 122 | 123 | # Check permissions 124 | if [[ $EUID -ne 0 ]]; then 125 | echo >&2 " [ERROR] This script requires privileged access to system files" 126 | exit 4 127 | fi 128 | 129 | # Check requirements 130 | if [[ "${CASSANDRA_ENABLE}" -gt 0 ]] && [[ "${CASSANDRA_DISABLE}" -gt 0 ]]; then 131 | echo >&2 " [ERROR] Enable (-E) and Disable (-D) options can not be used together." 132 | exit 5 133 | fi 134 | 135 | # Backup configuration files 136 | if [[ -f ${CASSANDRA_ENV} ]]; then 137 | cp ${CASSANDRA_ENV} ${CASSANDRA_ENV}.${__TS__}.bck 138 | fi 139 | if [[ -f ${CASSANDRA_YAML} ]]; then 140 | cp ${CASSANDRA_YAML} ${CASSANDRA_YAML}.${__TS__}.bck 141 | fi 142 | 143 | # Configure memory settings 144 | if [[ "x${CASSANDRA_HEAP_MAXSIZE}" = "x" ]] && [[ "x${CASSANDRA_HEAP_NEWSIZE}" = "x" ]]; then 145 | echo " [INFO] Using default memory settings... Memory allocations will be calculated every time Cassandra starts." 146 | else 147 | if [[ "x${CASSANDRA_HEAP_MAXSIZE}" = "x" ]] || [[ "x${CASSANDRA_HEAP_NEWSIZE}" = "x" ]]; then 148 | echo " [ERROR] Set Cassandra Max Heap Size (-m) and Cassandra New Heap Size in pair (-n)." 149 | exit 6 150 | else 151 | sudo sed -i -r -e "s/#HEAP_NEWSIZE=/HEAP_NEWSIZE=/;/^HEAP_NEWSIZE=/s/=.*/=\"${CASSANDRA_HEAP_NEWSIZE}\"/" ${CASSANDRA_ENV} 152 | sudo sed -i -r -e "s/#MAX_HEAP_SIZE=/MAX_HEAP_SIZE=/;/^MAX_HEAP_SIZE=/s/=.*/=\"${CASSANDRA_HEAP_MAXSIZE}\"/" ${CASSANDRA_ENV} 153 | fi 154 | fi 155 | 156 | # Configure cluster name 157 | if ! [[ "x${CASSANDRA_CLUSTER_NAME}" = "x" ]]; then 158 | sed -i -r -e "/^cluster_name:/s/:.*/: '${CASSANDRA_CLUSTER_NAME}'/" ${CASSANDRA_YAML} 159 | fi 160 | 161 | # Configure listen address 162 | if ! [[ "x${CASSANDRA_IP_ADDRESS}" = "x" ]]; then 163 | sed -i -r -e "/^listen_address:/s/:.*/: ${CASSANDRA_IP_ADDRESS}/" ${CASSANDRA_YAML} 164 | sed -i -r -e "/^broadcast_address:/s/:.*/: ${CASSANDRA_IP_ADDRESS}/" ${CASSANDRA_YAML} 165 | sed -i -r -e "/^broadcast_rpc_address:/s/:.*/: ${CASSANDRA_IP_ADDRESS}/" ${CASSANDRA_YAML} 166 | fi 167 | 168 | # Configure bootstrap 169 | if [[ "${CASSANDRA_BOOTSTRAP}" -gt 0 ]]; then 170 | sudo sed -i -r -e '/auto_bootstrap:/{h;s/#*auto_bootstrap:.*/auto_bootstrap: true/};${x;/^$/{s//\nauto_bootstrap: true/;H};x}' ${CASSANDRA_YAML} 171 | fi 172 | 173 | # Configure tokens 174 | if ! [[ "x${CASSANDRA_TOKENS}" = "x" ]]; then 175 | sed -i -r -e "/^num_tokens:/s/:.*/: ${CASSANDRA_TOKENS}/" ${CASSANDRA_YAML} 176 | fi 177 | 178 | # Configure snitch to multi-region 179 | if [[ "${CASSANDRA_MULTIREGION}" -gt 0 ]]; then 180 | sed -i -r -e "/^endpoint_snitch:/s/:.*/: EC2MultiRegionSnitch/" ${CASSANDRA_YAML} 181 | fi 182 | 183 | # Configure seeds 184 | if [[ ${#__TMP_SEEDS__[@]} -gt 0 ]]; then 185 | CASSANDRA_SEEDS="${__TMP_SEEDS__[@]}" 186 | sed -i -r -e "/- seeds:/s/:.*/: \"${CASSANDRA_SEEDS// /,}\"/" ${CASSANDRA_YAML} 187 | fi 188 | 189 | # Enable the service 190 | [[ "${CASSANDRA_ENABLE}" -gt 0 ]] && systemctl enable cassandra.service 191 | 192 | # Disable the service 193 | [[ "${CASSANDRA_DISABLE}" -gt 0 ]] && systemctl disable cassandra.service 194 | 195 | # Start the service 196 | if [[ "${CASSANDRA_START}" -gt 0 ]]; then 197 | echo " [INFO] Cassandra will start in ${CASSANDRA_WAIT} second(s)..." 198 | nohup sh -c "sleep ${CASSANDRA_WAIT} ; systemctl start cassandra.service" &> /dev/null & 199 | fi 200 | 201 | # Clean up unneeded backups 202 | diff -q ${CASSANDRA_ENV} ${CASSANDRA_ENV}.${__TS__}.bck &> /dev/null && rm -f ${CASSANDRA_ENV}.${__TS__}.bck || true 203 | diff -q ${CASSANDRA_YAML} ${CASSANDRA_YAML}.${__TS__}.bck &> /dev/null && rm -f ${CASSANDRA_YAML}.${__TS__}.bck || true 204 | 205 | # All done 206 | echo " [INFO] Configuration(s) successfully updated" 207 | exit 0 208 | -------------------------------------------------------------------------------- /files/bash_completion/nodetool: -------------------------------------------------------------------------------- 1 | have nodetool && have cqlsh && 2 | { 3 | 4 | show_keyspaces() 5 | { 6 | local ks=$(get_keyspaces) 7 | COMPREPLY=( $(compgen -W "$ks" -- "$1") ) 8 | } 9 | 10 | get_keyspaces() 11 | { 12 | [ -z "$keyspaces" ] && keyspaces=$(echo "DESCRIBE KEYSPACES" | cqlsh | egrep -v '^$') 13 | echo $keyspaces 14 | } 15 | 16 | show_datacenters() 17 | { 18 | cur=$1 19 | set|grep -q ^dcs || dcs=$(echo "select data_center from system.peers;"|cqlsh |tail -n +4|sort|uniq|awk '{if(length($1)>1) print $1}'|xargs) 20 | COMPREPLY=( $(compgen -W "$dcs" -- "$cur") ) 21 | } 22 | 23 | show_cfs() 24 | { 25 | local cur prev cfs 26 | prev=$1 27 | cur=$2 28 | cfs=$(get_cfs $1 $2) 29 | COMPREPLY=( $(compgen -W "$cfs" -- "$cur") ) 30 | } 31 | 32 | get_cfs() 33 | { 34 | local prev 35 | prev=$1 36 | [ -z "${cf[$prev]}" ] && cf[$prev]=$(echo "DESCRIBE COLUMNFAMILIES" | cqlsh -k ${prev} | egrep -v '^$') 37 | echo ${cf[$prev]} 38 | } 39 | 40 | show_last_cfs() 41 | { 42 | local cur cfs re 43 | cur=$1 44 | re=$(echo ${COMP_WORDS[@]:3:$(($COMP_CWORD - 3))} | sed -e 's/ /\\|/g') 45 | cfs=$(get_cfs ${COMP_WORDS[2]} | sed -e "s/$re//g") 46 | COMPREPLY=( $(compgen -W "$cfs" -- "${cur}") ) 47 | } 48 | 49 | _nodetool() 50 | { 51 | local cur prev ks 52 | COMPREPLY=() 53 | _get_comp_words_by_ref cur prev 54 | 55 | local shopt=' 56 | cfstats 57 | compactionstats 58 | compactionhistory 59 | decommission 60 | describecluster 61 | disablebackup 62 | disablebinary 63 | disablegossip 64 | disablehandoff 65 | disablethrift 66 | drain 67 | enablebackup 68 | enablebinary 69 | enablegossip 70 | enablehandoff 71 | enablethrift 72 | getcompactionthroughput 73 | getlogginglevels 74 | getstreamthroughput 75 | gossipinfo 76 | help 77 | invalidatecountercache 78 | invalidatekeycache 79 | invalidaterowcache 80 | join 81 | listsnapshots 82 | pausehandoff 83 | proxyhistograms 84 | rangekeysample 85 | reloadtriggers 86 | resetlocalschema 87 | resumehandoff 88 | ring 89 | setlogginglevel 90 | status 91 | statusbinary 92 | statusthrift 93 | stopdaemon 94 | tpstats 95 | version 96 | ' 97 | 98 | local lngopt=' 99 | cfhistograms 100 | cleanup 101 | clearsnapshot 102 | compact 103 | describering 104 | disableautocompaction 105 | enableautocompaction 106 | flush 107 | getcompactionthreshold 108 | getendpoints 109 | getsstables 110 | info 111 | move 112 | netstats 113 | rebuild 114 | rebuild_index 115 | refresh 116 | removenode 117 | repair 118 | scrub 119 | setcachecapacity 120 | setcachekeystosave 121 | setcompactionthreshold 122 | setcompactionthroughput 123 | setstreamthroughput 124 | settraceprobability 125 | snapshot 126 | stop 127 | taketoken 128 | truncatehints 129 | upgradesstables 130 | ' 131 | 132 | local optwks=' 133 | cfhistograms 134 | cleanup 135 | clearsnapshot 136 | compact 137 | describering 138 | flush 139 | getcompactionthreshold 140 | getendpoints 141 | getsstables 142 | rebuild_index 143 | refresh 144 | repair 145 | scrub 146 | setcompactionthreshold 147 | snapshot 148 | ' 149 | 150 | local optwcfs=' 151 | cleanup 152 | compact 153 | disableautocompaction 154 | enableautocompaction 155 | flush 156 | repair 157 | scrub 158 | upgradesstables 159 | ' 160 | 161 | if [[ $COMP_CWORD -eq 1 ]] ; then 162 | COMPREPLY=( $(compgen -W "${lngopt} ${shopt}" -- "${cur}") ) 163 | elif [[ $(echo "${lngopt}"|egrep -c "\b${prev}\b") -gt 0 ]] ; then 164 | if echo $optwks|grep -q "\b$prev\b" ; then 165 | show_keyspaces "${cur}" 166 | else 167 | case "${prev}" in 168 | removenode) 169 | # we don't want to lose time using nodetool status a 2nd time 170 | # in case of force or status 171 | if [[ "${cur}" =~ ^(f|s) ]] ; then 172 | COMPREPLY=( $(compgen -W "status force" -- "${cur}") ) 173 | else 174 | [ -z "$IDS" ] && IDS=$(nodetool status|grep %|awk '{print $7}'|xargs) 175 | COMPREPLY=( $(compgen -W "status force $IDS" -- "${cur}") ) 176 | fi 177 | return 0 178 | ;; 179 | stop) 180 | COMPREPLY=( $(compgen -W "COMPACTION VALIDATION CLEANUP SCRUB INDEX_BUILD" -- "${cur}") ) 181 | return 0 182 | ;; 183 | info) 184 | COMPREPLY=( $(compgen -W "-T --tokens" -- "${cur}") ) 185 | return 0 186 | ;; 187 | rebuild) 188 | show_datacenters "${cur}" 189 | return 0 190 | ;; 191 | upgradesstables) 192 | ks=$(get_keyspaces) 193 | COMPREPLY=( $(compgen -W "-a --include-all-sstables $ks" -- "${cur}") ) 194 | return 0 195 | ;; 196 | esac 197 | fi 198 | elif [[ $COMP_CWORD -eq 3 ]] ; then 199 | case "${COMP_WORDS[1]}" in 200 | cfhistograms|cleanup|compact|flush|getcompactionthreshold|getendpoints|getsstables|rebuild_index|refresh|repair|scrub|setcompactionthreshold) 201 | show_cfs ${prev} ${cur} 202 | return 0 203 | ;; 204 | upgradesstables) 205 | if [[ ! ${prev} == -* ]]; then 206 | show_cfs ${prev} ${cur} 207 | fi 208 | return 0 209 | ;; 210 | snapshot) 211 | COMPREPLY=( $(compgen -W "-cf" -- "${cur}") ) 212 | return 0 213 | ;; 214 | esac 215 | elif [[ "${optwcfs}" == *${COMP_WORDS[1]}* ]] ; then 216 | show_last_cfs ${cur} 217 | elif [[ $COMP_CWORD -eq 4 && ${COMP_WORDS[1]} == "snapshot" ]] ; then 218 | show_cfs ${COMP_WORDS[2]} ${cur} 219 | elif [[ $COMP_CWORD -eq 5 && ${COMP_WORDS[1]} == "snapshot" ]] ; then 220 | COMPREPLY=( $(compgen -W "-t" -- "${cur}") ) 221 | fi 222 | } 223 | complete -F _nodetool nodetool 224 | } 225 | -------------------------------------------------------------------------------- /cassandra.json: -------------------------------------------------------------------------------- 1 | { 2 | "_copyright": "2016-2022, Frederico Martins", 3 | "_author": "Frederico Martins ", 4 | "_license": "SPDX-License-Identifier: MIT", 5 | "variables": { 6 | "aws_access_key": "{{env `aws_access_key`}}", 7 | "aws_ami_name": "cassandra", 8 | "aws_ami_name_prefix": "", 9 | "aws_instance_type": "t2.micro", 10 | "aws_region": "{{env `aws_region`}}", 11 | "aws_secret_key": "{{env `aws_secret_key`}}", 12 | "aws_ssh_username": "admin", 13 | "cassandra_uid": "2002", 14 | "cassandra_version": "{{env `cassandra_version`}}", 15 | "java_build_number": "12", 16 | "java_major_version": "8", 17 | "java_token": "e758a0de34e24606bca991d704f6dcbf", 18 | "java_update_version": "151", 19 | "os_short_arch": "x64", 20 | "system_locale": "en_US" 21 | }, 22 | "builders": [{ 23 | "type": "amazon-ebs", 24 | "access_key": "{{user `aws_access_key`}}", 25 | "secret_key": "{{user `aws_secret_key`}}", 26 | "region": "{{user `aws_region`}}", 27 | "instance_type": "{{user `aws_instance_type`}}", 28 | "ssh_username": "{{user `aws_ssh_username`}}", 29 | "associate_public_ip_address": true, 30 | "ami_name": "{{user `aws_ami_name_prefix`}}{{user `aws_ami_name`}}-{{user `cassandra_version`}}-({{isotime \"20060102150405\"}})", 31 | "source_ami_filter": { 32 | "filters": { 33 | "architecture": "x86_64", 34 | "name": "debian-jessie-*", 35 | "root-device-type": "ebs", 36 | "virtualization-type": "hvm" 37 | }, 38 | "owners": ["379101102735"], 39 | "most_recent": true 40 | } 41 | }], 42 | "provisioners": [ 43 | { 44 | "type": "file", 45 | "source": "files/sysctl/", 46 | "destination": "/tmp" 47 | }, 48 | { 49 | "type": "file", 50 | "source": "files/systemd/", 51 | "destination": "/tmp" 52 | }, 53 | { 54 | "type": "file", 55 | "source": "files/bash_completion/", 56 | "destination": "/tmp" 57 | }, 58 | { 59 | "type": "file", 60 | "source": "files/cassandra/", 61 | "destination": "/tmp" 62 | }, 63 | { 64 | "type": "shell", 65 | "inline_shebang": "/bin/bash -e", 66 | "environment_vars": [ 67 | "DEBIAN_FRONTEND=noninteractive" 68 | ], 69 | "inline": [ 70 | "unset HISTFILE", 71 | "history -cw", 72 | "echo === Waiting for Cloud-Init ===", 73 | "timeout 180 /bin/bash -c 'until stat /var/lib/cloud/instance/boot-finished &>/dev/null; do echo waiting...; sleep 6; done'", 74 | "echo === System Packages ===", 75 | "echo 'deb http://ftp.debian.org/debian jessie-backports main contrib non-free' | sudo tee /etc/apt/sources.list.d/backports.list > /dev/null", 76 | "sudo apt-get -qq update", 77 | "sudo apt-get -y -qq install --no-install-recommends apt-transport-https apt-show-versions bash-completion logrotate ntp ntpdate htop vim wget curl dbus bmon nmon parted wget curl sudo rsyslog ethtool unzip zip telnet tcpdump strace tar libyaml-0-2 lsb-base lsb-release xfsprogs sysfsutils", 78 | "sudo apt-get -y -qq install --no-install-recommends -t jessie-backports python python-minimal python-openssl python-crypto", 79 | "sudo apt-get -y -qq --purge autoremove", 80 | "sudo apt-get autoclean", 81 | "sudo apt-get clean", 82 | "echo === Python Settings ===", 83 | "echo -e 'export PYTHONHASHSEED=0\\nexport PYTHONIOENCODING=UTF-8\\nexport PIP_DISABLE_PIP_VERSION_CHECK=1' | sudo tee /etc/profile.d/python.sh > /dev/null", 84 | "sudo sed -i -r -e 's/#DefaultEnvironment/DefaultEnvironment/;/DefaultEnvironment/s/([^=])$/\\1 /;/DefaultEnvironment/s/$/\"PYTHONHASHSEED=0\" \"PYTHONIOENCODING=UTF-8\" \"PIP_DISABLE_PIP_VERSION_CHECK=1\"/' /etc/systemd/system.conf", 85 | "echo === System Settings ===", 86 | "echo 'dash dash/sh boolean false' | sudo debconf-set-selections", 87 | "sudo dpkg-reconfigure -f noninteractive dash", 88 | "sudo update-locale LC_CTYPE={{user `system_locale`}}.UTF-8", 89 | "echo 'export TZ=:/etc/localtime' | sudo tee /etc/profile.d/tz.sh > /dev/null", 90 | "sudo update-alternatives --set editor /usr/bin/vim.basic", 91 | "sudo sed -i -r -e '/127.0.1.1/s/^#*/#/' /etc/cloud/templates/hosts.debian.tmpl", 92 | "echo === Sysctl ===", 93 | "sudo cp /tmp/50-cassandra.conf /etc/sysctl.d/", 94 | "sudo chown root:root /etc/sysctl.d/50-cassandra.conf", 95 | "sudo chmod 0644 /etc/sysctl.d/50-cassandra.conf", 96 | "sudo sysctl -p /etc/sysctl.d/50-cassandra.conf", 97 | "echo === Bash Completion ===", 98 | "sudo cp /tmp/nodetool /etc/bash_completion.d/", 99 | "sudo chown root:root /etc/bash_completion.d/nodetool", 100 | "sudo chmod 0644 /etc/bash_completion.d/nodetool", 101 | "echo === Java ===", 102 | "sudo mkdir /opt/java", 103 | "curl -sL --retry 3 --insecure --header 'Cookie: oraclelicense=accept-securebackup-cookie;' 'http://download.oracle.com/otn-pub/java/jdk/{{user `java_major_version`}}u{{user `java_update_version`}}-b{{user `java_build_number`}}/{{user `java_token`}}/jre-{{user `java_major_version`}}u{{user `java_update_version`}}-linux-{{user `os_short_arch`}}.tar.gz' | sudo tar xz --strip-components=1 -C /opt/java/", 104 | "sudo chown -R root:root /opt/java", 105 | "echo 'export JAVA_HOME=/opt/java' | sudo tee /etc/profile.d/java.sh > /dev/null", 106 | "sudo sed -i -r -e 's/#DefaultEnvironment/DefaultEnvironment/;/DefaultEnvironment/s/([^=])$/\\1 /;/DefaultEnvironment/s/$/\"JAVA_HOME=\\/opt\\/java\"/' /etc/systemd/system.conf", 107 | "sudo gzip -r /opt/java/man/man1", 108 | "for program in /opt/java/bin/*; do name=${program##*/}; manpage=''; [[ -f /opt/java/man/man1/${name}.1.gz ]] && manpage=\"--slave /usr/share/man/man1/${name}.1.gz ${name}.1.gz /opt/java/man/man1/${name}.1.gz\"; [[ -x ${program} && ! -L ${program} ]] && sudo update-alternatives --install /usr/bin/${name} ${name} /opt/java/bin/${name} 1 ${manpage}; done", 109 | "echo === Cassandra ===", 110 | "sudo groupadd -g {{user `cassandra_uid`}} cassandra", 111 | "sudo useradd -m -u {{user `cassandra_uid`}} -g {{user `cassandra_uid`}} -c 'Apache Cassandra' -s /bin/bash -d /srv/cassandra cassandra", 112 | "curl -sL --retry 3 --insecure 'http://archive.apache.org/dist/cassandra/{{user `cassandra_version`}}/apache-cassandra-{{user `cassandra_version`}}-bin.tar.gz' | sudo tar xz --strip-components=1 -C /srv/cassandra/", 113 | "sudo pycompile /srv/cassandra/pylib/cqlshlib", 114 | "sudo mkdir -p /data/cassandra", 115 | "sudo mkdir -p /var/{log,run}/cassandra", 116 | "sudo ln -s /var/log/cassandra /srv/cassandra/logs", 117 | "sudo ln -s /data/cassandra /srv/cassandra/data", 118 | "sudo touch /srv/cassandra/conf/jvm.options", 119 | "sudo sed -i -r -e \"s/# *cluster_name:/cluster_name:/;/^cluster_name:/s/:.*/: 'Cassandra Cluster'/\" /srv/cassandra/conf/cassandra.yaml", 120 | "sudo sed -i -r -e 's/# *num_tokens:/num_tokens:/;/^num_tokens:/s/:.*/: 4/' /srv/cassandra/conf/cassandra.yaml", 121 | "sudo sed -i -r -e '/- seeds:/s/:.*/: \"127.0.0.1\"/' /srv/cassandra/conf/cassandra.yaml", 122 | "sudo sed -i -r -e 's/# *listen_address:/listen_address:/;/^listen_address:/s/:.*/: 127.0.0.1/' /srv/cassandra/conf/cassandra.yaml", 123 | "sudo sed -i -r -e 's/# *broadcast_address:/broadcast_address:/;/^broadcast_address:/s/:.*/: 127.0.0.1/' /srv/cassandra/conf/cassandra.yaml", 124 | "sudo sed -i -r -e 's/# *start_rpc:/start_rpc:/;/^start_rpc:/s/:.*/: true/' /srv/cassandra/conf/cassandra.yaml", 125 | "sudo sed -i -r -e 's/# *rpc_address:/rpc_address:/;/^rpc_address:/s/:.*/: 0.0.0.0/' /srv/cassandra/conf/cassandra.yaml", 126 | "sudo sed -i -r -e 's/# *broadcast_rpc_address:/broadcast_rpc_address:/;/^broadcast_rpc_address:/s/:.*/: 127.0.0.1/' /srv/cassandra/conf/cassandra.yaml", 127 | "sudo sed -i -r -e '/^endpoint_snitch:/s/:.*/: Ec2Snitch/' /srv/cassandra/conf/cassandra.yaml", 128 | "sudo sed -i -r -e '/^#/! {/HeapDumpOnOutOfMemoryError/s/^/#/}' /srv/cassandra/conf/jvm.options", 129 | "echo -e 'export CASSANDRA_HOME=/srv/cassandra\\nexport CASSANDRA_CONF=$CASSANDRA_HOME/conf\\nexport PYTHONPATH=$CASSANDRA_HOME/pylib/\\nexport PATH=$PATH:$CASSANDRA_HOME/bin:$CASSANDRA_HOME/tools/bin\\nexport CLASSPATH=$CASSANDRA_HOME/lib/*:$CASSANDRA_HOME/tools/lib/*' | sudo tee /etc/profile.d/cassandra.sh > /dev/null", 130 | "sudo sed -i -r -e 's/#DefaultEnvironment/DefaultEnvironment/;/DefaultEnvironment/s/([^=])$/\\1 /;/DefaultEnvironment/s/$/\"CASSANDRA_HOME=\\/srv\\/cassandra\" \"CASSANDRA_CONF=\\/srv\\/cassandra\\/conf\" \"PYTHONPATH=\\/srv\\/cassandra\\/pylib\\/\" \"CLASSPATH=\\/srv\\/cassandra\\/lib\\/*:\\/srv\\/cassandra\\/tools\\/lib\\/*\"/' /etc/systemd/system.conf", 131 | "sudo chown -R cassandra:cassandra /srv/cassandra /data/cassandra /var/log/cassandra /var/run/cassandra", 132 | "sudo cp /tmp/cassandra.service /lib/systemd/system/", 133 | "sudo systemctl daemon-reload", 134 | "sudo systemctl disable cassandra.service", 135 | "sudo cp /tmp/cassandra_config /usr/local/bin/", 136 | "sudo chown root:staff /usr/local/bin/cassandra_config", 137 | "sudo chmod 0755 /usr/local/bin/cassandra_config", 138 | "echo === Extra System Settings ===", 139 | "sudo sed -r -i -e 's/.*(GRUB_CMDLINE_LINUX_DEFAULT)=\"(.*)\"/\\1=\"\\2 elevator=deadline\"/' /etc/default/grub", 140 | "sudo update-grub2", 141 | "echo === System Cleanup ===", 142 | "sudo rm -f /root/.bash_history", 143 | "sudo rm -f /home/{{user `aws_ssh_username`}}/.bash_history", 144 | "sudo rm -f /var/log/wtmp", 145 | "sudo rm -f /var/log/btmp", 146 | "sudo rm -rf /var/log/installer", 147 | "sudo rm -rf /var/lib/cloud/instances", 148 | "sudo rm -rf /tmp/* /var/tmp/* /tmp/.*-unix", 149 | "sudo find /var/cache -type f -delete", 150 | "sudo find /var/log -type f | while read f; do echo -n '' | sudo tee $f > /dev/null; done;", 151 | "sudo find /var/lib/apt/lists -not -name lock -type f -delete", 152 | "sudo sync", 153 | "echo === All Done ===" 154 | ] 155 | } 156 | ] 157 | } 158 | --------------------------------------------------------------------------------