diff --git a/Cassandra/package/Classes/CassandraCluster.yaml b/Cassandra/package/Classes/CassandraCluster.yaml new file mode 100644 index 00000000..1673891a --- /dev/null +++ b/Cassandra/package/Classes/CassandraCluster.yaml @@ -0,0 +1,77 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Namespaces: + =: io.murano.apps.apache + std: io.murano + res: io.murano.resources + sys: io.murano.system + + +Name: CassandraCluster + +Extends: std:Application + +Properties: + name: + Contract: $.string().notNull() + + seedNodes: + Contract: [$.class(CassandraNode).notNull()] + + regularNodes: + Contract: [$.class(CassandraNode).notNull()] + +Methods: + initialize: + Body: + - $._environment: $.find(std:Environment).require() + + deploy: + Body: + - If: not $.getAttr(deployed, false) + Then: + - $._environment.reporter.report($this, 'Creating VMs for Cassandra cluster') + + # Spawn VMs in parallel + - Parallel: + - $.seedNodes.pselect($.spawnInstance()) + - $.regularNodes.pselect($.spawnInstance()) + + # Collect internal IPs of seed nodes + - $seedNodesAsString: join(',', $.seedNodes.select($.getInternalIp())) + + # Deploy Cassandra with default conf + - Parallel: + - $.seedNodes.pselect($.deployInstance()) + - $.regularNodes.pselect($.deployInstance()) + + - $msg: format('Deployed {0} seed nodes and {1} usual nodes', len($.seedNodes), len($.regularNodes)) + - $._environment.reporter.report($this, $msg) + + # Update configuration (identical on all nodes) + - Parallel: + - $.seedNodes.pselect($.updateConfiguration($this.name, $seedNodesAsString)) + - $.regularNodes.pselect($.updateConfiguration($this.name, $seedNodesAsString)) + + # Restart nodes for changes to take an effect + - $msg: format('Restarting all nodes in the cluster') + - $._environment.reporter.report($this, $msg) + - $.seedNodes.pselect($.restartCassandra(delay => 1)) + + # No parallel there because usual nodes have to be started one by one + # Uses delay of restart for usual nodes to give seed nodes time on slow envs + - $.regularNodes.select($.restartCassandra(delay => 120)) + + - $._environment.reporter.report($this, 'Cassandra cluster is deployed') + - $._environment.reporter.report($this, 'Log in to any instance and use "nodetool status" to check') + - $.setAttr(deployed, true) diff --git a/Cassandra/package/Classes/CassandraNode.yaml b/Cassandra/package/Classes/CassandraNode.yaml new file mode 100644 index 00000000..1f08d0ea --- /dev/null +++ b/Cassandra/package/Classes/CassandraNode.yaml @@ -0,0 +1,119 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Namespaces: + =: io.murano.apps.apache + std: io.murano + res: io.murano.resources + sys: io.murano.system + + +Name: CassandraNode + +Extends: std:Application + +Properties: + instance: + Contract: $.class(res:Instance).notNull() + +Methods: + initialize: + Body: + - $._environment: $.find(std:Environment).require() + - $.resources: new(sys:Resources) + + updateConfiguration: + Arguments: + - clusterName: + Contract: $.string().notNull() + - seedNodes: + Contract: $.string().notNull() + + Body: + # Listen address is internal (so it gets resolved by node itself correctly) + - $listenAddress: $.instance.ipAddresses[0] + - $template: $.resources.yaml('UpdateCassandraYaml.template').bind(dict( + clusterName => $clusterName, + seedNodes => $seedNodes, + listenAddress => $listenAddress + )) + - $msg: format('Updating Cassandra configuration at node "{0}"', $listenAddress) + - $._environment.reporter.report($this, $msg) + - $.instance.agent.call($template, $.resources) + + + configureSecurityGroups: + Body: + # Based on Cassandra 2.1 defaults + - $securityGroupIngress: + # Cassandra JMX monitoring port + - ToPort: 7199 + FromPort: 7199 + IpProtocol: tcp + External: true + # Cassandra inter-node cluster communication + - ToPort: 7000 + FromPort: 7000 + IpProtocol: tcp + External: true + # Cassandra SSL inter-node cluster communication + - ToPort: 7001 + FromPort: 7001 + IpProtocol: tcp + External: true + # Cassandra client port (Thrift) + - ToPort: 9160 + FromPort: 9160 + IpProtocol: tcp + External: true + # Cassandra client port + - ToPort: 9042 + FromPort: 9042 + IpProtocol: tcp + External: true + - $._environment.securityGroupManager.addGroupIngress($securityGroupIngress) + + spawnInstance: + Body: + - $msg: format('Creating a VM for Cassandra node "{0}"', $.instance.name) + - $._environment.reporter.report($this, $msg) + - $.configureSecurityGroups() + - $.instance.deploy() + - $address: $.instance.ipAddresses[0] + - $._environment.reporter.report($this, 'Instance "{0}" is created'.format($address)) + + deployInstance: + Body: + - If: not $.getAttr(deployed, false) + Then: + - $address: $.instance.ipAddresses[0] + - $._environment.reporter.report($this, 'Deploying Cassandra node "{0}"'.format($address)) + - $template: $.resources.yaml('DeployCassandra.template') + - $.instance.agent.call($template, $.resources) + - $.setAttr(deployed, true) + + getInternalIp: + Body: + - Return: $.instance.ipAddresses[0] + + ## Restarts an existing Cassandra after given delay (in seconds) + restartCassandra: + Arguments: + - delay: + Contract: $.int().notNull() + Body: + - $msg: format('Restarting Cassandra node "{0}"', $.instance.name) + - $._environment.reporter.report($this, $msg) + - $template: $.resources.yaml('RestartCassandra.template').bind(dict( + delay => $delay + )) + - $.instance.agent.call($template, $.resources) diff --git a/Cassandra/package/Resources/DeployCassandra.template b/Cassandra/package/Resources/DeployCassandra.template new file mode 100644 index 00000000..62fb94bf --- /dev/null +++ b/Cassandra/package/Resources/DeployCassandra.template @@ -0,0 +1,31 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +FormatVersion: 2.0.0 +Version: 1.0.0 +Name: Deploy Cassandra + +Parameters: + appName: $appName + +Body: | + return deploy(args.appName).stdout + +Scripts: + deploy: + Type: Application + Version: 1.0.0 + EntryPoint: deployCassandra.sh + Files: [] + Options: + captureStdout: false + captureStderr: true diff --git a/Cassandra/package/Resources/RestartCassandra.template b/Cassandra/package/Resources/RestartCassandra.template new file mode 100644 index 00000000..c3768c84 --- /dev/null +++ b/Cassandra/package/Resources/RestartCassandra.template @@ -0,0 +1,32 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +FormatVersion: 2.0.0 +Version: 1.0.0 +Name: Restart Cassandra + +Parameters: + delay: $delay + +Body: | + restart('{0}'.format(args.delay)) + +Scripts: + restart: + Type: Application + Version: 1.0.0 + EntryPoint: restartCassandra.sh + Files: [] + Options: + captureStdout: true + captureStderr: false + verifyExitcode: false diff --git a/Cassandra/package/Resources/UpdateCassandraYaml.template b/Cassandra/package/Resources/UpdateCassandraYaml.template new file mode 100644 index 00000000..cb9f24d7 --- /dev/null +++ b/Cassandra/package/Resources/UpdateCassandraYaml.template @@ -0,0 +1,34 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +FormatVersion: 2.0.0 +Version: 1.0.0 +Name: Update Cassandra Yaml + +Parameters: + clusterName: $clusterName + seedNodes: $seedNodes + listenAddress: $listenAddress + +Body: | + configure('{0} {1} {2}'.format(args.clusterName, args.seedNodes, args.listenAddress)) + +Scripts: + configure: + Type: Application + Version: 1.0.0 + EntryPoint: updateCassandraYaml.sh + Files: [] + Options: + captureStdout: true + captureStderr: true + diff --git a/Cassandra/package/Resources/scripts/deployCassandra.sh b/Cassandra/package/Resources/scripts/deployCassandra.sh new file mode 100644 index 00000000..95ae475b --- /dev/null +++ b/Cassandra/package/Resources/scripts/deployCassandra.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +## Add public keys and signatures +gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D +gpg --export --armor F758CE318D77295D | sudo apt-key add - + +# Starting from Debian 0.7.5, more keys +gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 +gpg --export --armor 2B5C1B00 | sudo apt-key add - + +gpg --keyserver pgp.mit.edu --recv-keys 0353B12C +gpg --export --armor 0353B12C | sudo apt-key add - + +## Add Apache Software Foundation repositories +sudo sh -c 'echo "deb http://www.apache.org/dist/cassandra/debian 21x main" > /etc/apt/sources.list.d/apache-cassandra.sources.list' +sudo sh -c 'echo "deb-src http://www.apache.org/dist/cassandra/debian 21x main" >> /etc/apt/sources.list.d/apache-cassandra.sources.list' + +sudo apt-get update + +## Install from package +sudo apt-get -y install cassandra cassandra-tools + +## Stop Cassandra and delete initial tables (to change name from Test Cluster) +sudo service cassandra stop +sudo rm -rf /var/lib/cassandra/data/* +sudo rm -rf /var/lib/cassandra/commitlog/* +sudo rm -rf /var/lib/cassandra/saved_caches/* + diff --git a/Cassandra/package/Resources/scripts/restartCassandra.sh b/Cassandra/package/Resources/scripts/restartCassandra.sh new file mode 100644 index 00000000..b4e32d85 --- /dev/null +++ b/Cassandra/package/Resources/scripts/restartCassandra.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +## Restart service for any changes to take the effect +# Sleep for some time added as a helper +TIME="$1" + +sleep $TIME +sudo service cassandra restart diff --git a/Cassandra/package/Resources/scripts/updateCassandraYaml.sh b/Cassandra/package/Resources/scripts/updateCassandraYaml.sh new file mode 100644 index 00000000..78a5a73c --- /dev/null +++ b/Cassandra/package/Resources/scripts/updateCassandraYaml.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +CLUSTER_NAME="$1" +SEED_NODES="$2" +LISTEN_ADDRESS="$3" + +## Configure Cassandra to use seed nodes +# Set cluster name +sed -e "s/cluster_name:.*/cluster_name: \'$CLUSTER_NAME\'/g" -i /etc/cassandra/cassandra.yaml +# Seed provider class name +sed -e "s/- class_name:.*/- class_name: org.apache.cassandra.locator.SimpleSeedProvider/g" -i /etc/cassandra/cassandra.yaml +# Set seed nodes - nodes used to bootstrap other nodes +sed -e "s/seeds:.*/seeds: \"$SEED_NODES\"/g" -i /etc/cassandra/cassandra.yaml +# Set listen address and endpoint snitch class +sed -e "s/listen_address:.*/listen_address: $LISTEN_ADDRESS/g" -i /etc/cassandra/cassandra.yaml +sed -e "s/endpoint_snitch:.*/endpoint_snitch: GossipingPropertyFileSnitch/g" -i /etc/cassandra/cassandra.yaml +# Set RPC address +sed -e "s/^rpc_address:.*/rpc_address: 0.0.0.0/g" -i /etc/cassandra/cassandra.yaml +sed -e "s/#\s*broadcast_rpc_address:.*/broadcast_rpc_address: $LISTEN_ADDRESS/g" -i /etc/cassandra/cassandra.yaml + diff --git a/Cassandra/package/UI/ui.yaml b/Cassandra/package/UI/ui.yaml new file mode 100644 index 00000000..4c05f222 --- /dev/null +++ b/Cassandra/package/UI/ui.yaml @@ -0,0 +1,134 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Version: 2 + +Templates: + seedNode: + ?: + type: io.murano.apps.apache.CassandraNode + instance: + ?: + type: io.murano.resources.LinuxMuranoInstance + name: generateHostname($.appConfiguration.unitNamingPattern, $index) + flavor: $.instanceConfiguration.flavor + image: $.instanceConfiguration.osImage + assignFloatingIp: $.appConfiguration.assignFloatingIP + keyname: $.instanceConfiguration.keyPair + availabilityZone: $.instanceConfiguration.availabilityZone + + regularNode: + ?: + type: io.murano.apps.apache.CassandraNode + instance: + ?: + type: io.murano.resources.LinuxMuranoInstance + name: generateHostname($.appConfiguration.unitNamingPattern, $index + $.appConfiguration.countOfSeedNodes) + flavor: $.instanceConfiguration.flavor + image: $.instanceConfiguration.osImage + assignFloatingIp: $.appConfiguration.assignFloatingIP + keyname: $.instanceConfiguration.keyPair + availabilityZone: $.instanceConfiguration.availabilityZone + +Application: + ?: + type: io.murano.apps.apache.CassandraCluster + name: $.appConfiguration.name + seedNodes: repeat($seedNode, $.appConfiguration.countOfSeedNodes) + regularNodes: repeat($regularNode, $.appConfiguration.countOfRegularNodes) + +Forms: + - appConfiguration: + fields: + - name: license + type: string + description: Apache License, Version 2.0 + hidden: true + required: false + - name: name + type: string + label: Cluster Name + initial: CassandraCluster + description: >- + Enter a desired name for the application. Just A-Z, a-z, 0-9, dash and + underline are allowed + - name: countOfSeedNodes + type: integer + label: Count of seed nodes + initial: 1 + minValue: 0 + required: true + description: >- + Select the number of seed nodes. Seed nodes are used to bootstrap + other nodes(which is the process of a new node joining an existing + cluster) and setup the communication + - name: countOfRegularNodes + type: integer + label: Count of regular nodes + initial: 1 + required: true + minValue: 0 + description: >- + Select the number of Cassandra nodes (except seed nodes) + - name: assignFloatingIP + type: boolean + initial: true + label: Assign floating IP to nodes + description: >- + Check to assign floating IP to nodes + required: false + - name: unitNamingPattern + type: string + initial: cassandra-# + helpText: "# expands to machine sequence number" + required: false + description: >- + For your convenience instance hostname can be specified. + Enter a name or leave blank for random name generation. + regexpValidator: '^[a-zA-z][-_\w#]*$' + maxLength: 64 + errorMessages: + invalid: Just letters, numbers, underscores, sharps and hyphens are allowed. + label: Cassandra node hostname pattern + + - instanceConfiguration: + fields: + - name: title + type: string + required: false + hidden: true + description: Specify some instance parameters on which application would be created. + - name: flavor + type: flavor + label: Instance flavor + description: >- + Select one of the existing flavors. Consider that application performance + depends on this parameter. + - name: osImage + type: image + imageType: linux + label: Instance image + description: >- + Select a valid image for the application. Image should already be prepared and + registered in glance. + - name: keyPair + type: keypair + label: Key Pair + description: >- + Select the Key Pair to control access to instances. You can login to + instances using this KeyPair after the deployment. + required: false + - name: availabilityZone + type: azone + label: Availability zone + description: Select an availability zone where the application would be installed. + required: false diff --git a/Cassandra/package/logo.png b/Cassandra/package/logo.png new file mode 100644 index 00000000..445a2eb1 Binary files /dev/null and b/Cassandra/package/logo.png differ diff --git a/Cassandra/package/manifest.yaml b/Cassandra/package/manifest.yaml new file mode 100644 index 00000000..1f071ff1 --- /dev/null +++ b/Cassandra/package/manifest.yaml @@ -0,0 +1,24 @@ +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Format: 1.0 +Type: Application +FullName: io.murano.apps.apache.Cassandra +Name: Apache Cassandra +Description: | + Cassandra is a highly scalable, eventually consistent, distributed, + structured key-value store. +Author: 'Mirantis, Inc' +Tags: [NoSQL, Database, CQL, Apache, Java] +Classes: + io.murano.apps.apache.CassandraNode: CassandraNode.yaml + io.murano.apps.apache.CassandraCluster: CassandraCluster.yaml