Added Apache Cassandra application

The application allows to create clusters of Apache Cassandra.
Cassandra is a highly scalable, eventually consistent, distributed,
structured key-value store.

This application is written to be compatible with Kilo version.

Change-Id: Ia3bd4dc1bdf53cd29dd0b5973c9150cb72c3bd8b
This commit is contained in:
Vyacheslav Vakhlyuev 2015-12-02 14:45:36 +03:00
parent 70568f2e68
commit e45e769d08
11 changed files with 507 additions and 0 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/*

View File

@ -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

View File

@ -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

View File

@ -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

BIN
Cassandra/package/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -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