blob: b28984bfe17d1e358a1acd9be04b80141c45b401 [file] [log] [blame]
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#
# Brooklyn remote install script.
#
# Usage:
# brooklyn-install.sh [-h] [-q] [-s] [-e] [-g] [-u user] [-k key] [-r root] [-p port] [-v version] hostname
#
#set -x # DEBUG
function help() {
cat <<EOF
Brooklyn remote install script.
Options
-q Quiet install
-s Create and set up user account (set with -u option)
-e Set up random entropy for SSH
-g Generate a password for the Brooklyn admin user
-u Change the Brooklyn username (default 'brooklyn')
-r Change the remote root username (default 'root')
-k The private key to use for SSH (default '~/.ssh/id_rsa')
-p The SSH port to connect to (default 22)
-v Set the Brooklyn version to install (default '0.7.0-M1')
Usage
brooklyn-install.sh [-q] [-s] [-e] [-g] [-u user] [-r root] [-k key] [-p port] [-v version] hostname
Installs Brooklyn on the given hostname as 'brooklyn' or the specified
user. Optionally it creates and configures the Brooklyn user.
Passwordless SSH access as 'root' (or a user that has 'sudo' privileges) to the
remote host must be available, with the given key.
EOF
exit 0
}
# Global settings
LOG="brooklyn-install.log"
function log() {
if ! ${QUIET}; then
echo $@
fi
date +"Timestamp: %Y-%m-%d %H:%M:%S.%s" >> ${LOG}
if [ "$1" == "-n" ]; then
shift
fi
if [ "$*" != "..." ]; then
echo "Log: $*" | sed -e "s/\.\.\.//" >> ${LOG}
fi
}
function fail() {
log "...failed!"
error "$*"
}
function error() {
echo "Error: $*" | tee -a "${LOG}"
usage
}
function usage() {
echo "Usage: $(basename ${0}) [-h] [-q] [-s] [-e] [-g] [-u user] [-r root] [-k key] [-p port] [-v version] hostname"
exit 1
}
function retry() {
COMMAND="$@"
MAX=10
N=1
while [ ${N} -le ${MAX} ]; do
eval "${COMMAND}" 2>&1
if [ $? -eq 0 ]; then
return 0
else
echo -n "..."
sleep 1
N=$(($N + 1))
fi
done
return 1
}
# Default options
QUIET=false
GENERATE_PASSWORD=false
SETUP_USER=false
SETUP_RANDOM=false
BROOKLYN_VERSION="0.7.0-M1"
ROOT="root"
USER="brooklyn"
PRIVATE_KEY_FILE="${HOME}/.ssh/id_rsa"
SSH_PORT=22
while getopts ":hqsegu:r:k:p:v:" o; do
case "${o}" in
h) help
;;
q) QUIET=true
;;
s) SETUP_USER=true
;;
e) SETUP_RANDOM=true
;;
g) GENERATE_PASSWORD=true
log "Warning: Not supported in 0.7.0-M1 and earlier releases"
;;
u) USER="${OPTARG}"
SETUP_USER=true
;;
r) ROOT="${OPTARG}"
if [ "${ROOT}" != "root" ]; then
SUDO="sudo"
fi
;;
k) PRIVATE_KEY_FILE="${OPTARG}"
;;
p) SSH_PORT="${OPTARG}"
;;
v) BROOKLYN_VERSION="${OPTARG}"
;;
*) usage "Invalid option: $*"
;;
esac
done
shift $((OPTIND-1))
if [ $# -ne 1 ]; then
error "Must specify remote hostname as last argument"
fi
HOST="$1"
# Configure SSH
SSH_OPTS="-o StrictHostKeyChecking=no -p ${SSH_PORT}"
if [ -r "${PRIVATE_KEY_FILE}" ]; then
SSH_OPTS="${SSH_OPTS} -i ${PRIVATE_KEY_FILE}"
else
error "SSH private key '${PRIVATE_KEY_FILE}' not found"
fi
SSH_PUBLIC_KEY_DATA=$(ssh-keygen -y -f ${PRIVATE_KEY_FILE})
log "Installing Brooklyn ${BROOKLYN_VERSION}"
# Pre-requisites for this script
log -n "Checking '${HOST}:${SSH_PORT}' SSH connection... "
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} id" >> ${LOG} 2>&1 || fail "SSH connection as ${ROOT} failed"
log "...ok!"
# Install packages
log -n "Installing prerequisite packages..."
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} yum check-update || ${SUDO} apt-get update" >> ${LOG} 2>&1
for PACKAGE in "curl" "sed" "tar" "wget"; do
ssh ${SSH_OPTS} ${ROOT}@${HOST} "which ${PACKAGE} || { ${SUDO} yum -y --nogpgcheck -q install ${PACKAGE} || ${SUDO} apt-get -y --allow-unauthenticated install ${PACKAGE}; }" >> ${LOG} 2>&1
done
log "...done!"
# Install Java 7
log -n "Installing Java 7 packages..."
JAVA="java"
JAVA_HOME="/usr"
ssh ${SSH_OPTS} ${ROOT}@${HOST} "which ${JAVA} || { ${SUDO} yum -y --nogpgcheck -q install java-1.7.0-openjdk-devel || ${SUDO} apt-get -y --allow-unauthenticated install openjdk-7-jdk; }" >> ${LOG} 2>&1
for JVM in "jre" "jdk" "java-1.7.0-openjdk" "java-1.7.0-openjdk-amd64"; do
if ssh ${SSH_OPTS} ${ROOT}@${HOST} "test -d /usr/lib/jvm/${JVM}"; then
JAVA_HOME="/usr/lib/jvm/${JVM}/" && echo "Java: ${JAVA_HOME}" >> ${LOG}
fi
done
ssh ${SSH_OPTS} ${ROOT}@${HOST} "which ${JAVA} || test -x ${JAVA_HOME}/bin/${JAVA}" >> ${LOG} 2>&1 || fail "Java is not installed"
log "...done!"
# Increase linux kernel entropy for faster ssh connections
if ${SETUP_RANDOM}; then
log -n "Installing rng-tool to increase entropy..."
ssh ${SSH_OPTS} ${ROOT}@${HOST} "which rng-tools || { ${SUDO} yum -y --nogpgcheck -q install rng-tools || ${SUDO} apt-get -y --allow-unauthenticated install rng-tools; }" >> ${LOG} 2>&1
if ssh ${SSH_OPTS} ${ROOT}@${HOST} "test -f /etc/default/rng-tools"; then
echo "HRNGDEVICE=/dev/urandom" | ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} tee -a /etc/default/rng-tools" > /dev/null 2>&1
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} /etc/init.d/rng-tools start" >> ${LOG} 2>&1
else
echo "EXTRAOPTIONS=\"-r /dev/urandom\"" | ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} tee -a /etc/sysconfig/rngd" > /dev/null 2>&1
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} /etc/init.d/rngd start" >> ${LOG} 2>&1
fi
log "...done!"
fi
# Create Brooklyn user if required
if ! ssh ${SSH_OPTS} ${ROOT}@${HOST} "id ${USER} > /dev/null 2>&1"; then
if ! ${SETUP_USER}; then
error "User '${USER}' does not exist on ${HOST}"
fi
log -n "Creating '${USER}' user..."
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} useradd ${USER} -s /bin/bash -d /home/${USER} -m" >> ${LOG} 2>&1
ssh ${SSH_OPTS} ${ROOT}@${HOST} "id ${USER}" >> ${LOG} 2>&1 || fail "User was not created"
log "...done!"
fi
# Setup Brooklyn user
if ${SETUP_USER}; then
log -n "Setting up '${USER}' user... "
echo "${USER} ALL = (ALL) NOPASSWD: ALL" | ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} tee -a /etc/sudoers" > /dev/null 2>&1
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} sed -i.brooklyn.bak 's/.*requiretty.*/#brooklyn-removed-require-tty/' /etc/sudoers"
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} mkdir -p /home/${USER}/.ssh"
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} chmod 700 /home/${USER}/.ssh"
echo "${SSH_PUBLIC_KEY_DATA}" | ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} tee -a /home/${USER}/.ssh/authorized_keys" > /dev/null 2>&1
ssh ${SSH_OPTS} ${ROOT}@${HOST} "${SUDO} chown -R ${USER}.${USER} /home/${USER}/.ssh"
ssh ${SSH_OPTS} ${USER}@${HOST} "ssh-keygen -q -t rsa -N \"\" -f .ssh/id_rsa"
ssh ${SSH_OPTS} ${USER}@${HOST} "ssh-keygen -y -f .ssh/id_rsa >> .ssh/authorized_keys"
log "...done!"
fi
# Setup Brooklyn
log -n "Downloading Brooklyn distribution..."
ssh ${SSH_OPTS} ${USER}@${HOST} "curl -L -s -o brooklyn-${BROOKLYN_VERSION}.tar.gz http://search.maven.org/remotecontent?filepath=io/brooklyn/brooklyn-dist/${BROOKLYN_VERSION}/brooklyn-dist-${BROOKLYN_VERSION}-dist.tar.gz"
ssh ${SSH_OPTS} ${USER}@${HOST} "tar zxvf brooklyn-${BROOKLYN_VERSION}.tar.gz" >> ${LOG} 2>&1
ssh ${SSH_OPTS} ${USER}@${HOST} "test -x brooklyn-${BROOKLYN_VERSION}/bin/brooklyn" || fail "Brooklyn was not downloaded correctly"
log "...done!"
# Configure Brooklyn if no brooklyn.properties
if ! ssh ${SSH_OPTS} ${USER}@${HOST} "test -f .brooklyn/brooklyn.properties"; then
log -n "Configuring Brooklyn properties..."
ssh ${SSH_OPTS} ${USER}@${HOST} "mkdir -p .brooklyn"
ssh ${SSH_OPTS} ${USER}@${HOST} "curl -L -s -o .brooklyn/brooklyn.properties http://brooklyncentral.github.io/use/guide/quickstart/brooklyn.properties"
# Generate Brooklyn admin password
if ${GENERATE_PASSWORD}; then
GENERATED=$(dd if=/dev/random bs=1 count=32 2> /dev/null | uuencode -m - | sed -n 2p | tr -dc "A-Za-z0-9")
SALT=$(echo ${GENERATED} | cut -c1-4)
PASSWORD=$(echo ${GENERATED} | cut -c5-12)
which shasum && SHA256="shasum -a 256"
which sha256sum && SHA256="sha256sum"
HASH=$(printf '${SALT}${PASSWORD}\\00' | ${SHA256} | cut -d\ -f1)
ssh ${SSH_OPTS} ${USER}@${HOST} "tee -a .brooklyn/brooklyn.properties" > /dev/null 2>&1 <<EOF
brooklyn.webconsole.security.users = ${USER}
brooklyn.webconsole.security.user.${USER}.salt = ${SALT}
brooklyn.webconsole.security.user.${USER}.sha256 = ${HASH}
EOF
else
ssh ${SSH_OPTS} ${USER}@${HOST} "sed -i.bak 's/^# brooklyn.webconsole.security.provider = brooklyn.rest.security.provider.AnyoneSecurityProvider/brooklyn.webconsole.security.provider = brooklyn.rest.security.provider.AnyoneSecurityProvider/' .brooklyn/brooklyn.properties"
fi
log "...done!"
fi
# Install example Jars and catalog
log -n "Installing examples and configuring catalog..."
ssh ${SSH_OPTS} ${USER}@${HOST} "cat > .brooklyn/catalog.xml" <<EOF
<?xml version="1.0"?>
<catalog>
<name>Brooklyn Demos</name>
<template type="brooklyn.demo.WebClusterDatabaseExample" name="Demo Web Cluster with DB">
<description>Deploys a demonstration web application to a managed JBoss cluster with elasticity, persisting to MySQL</description>
<iconUrl>http://downloads.cloudsoftcorp.com/brooklyn/catalog/logos/JBoss_by_Red_Hat.png</iconUrl>
</template>
<template type="brooklyn.demo.GlobalWebFabricExample" name="Demo GeoDNS Web Fabric DB">
<description>Deploys a demonstration web application to JBoss clusters around the world</description>
<iconUrl>http://downloads.cloudsoftcorp.com/brooklyn/catalog/logos/JBoss_by_Red_Hat.png</iconUrl>
</template>
<template type="brooklyn.demo.SimpleCassandraCluster" name="Demo Cassandra Cluster">
<description>Deploys a demonstration Cassandra cluster</description>
<iconUrl>http://downloads.cloudsoftcorp.com/brooklyn/catalog/logos/cassandra-sq-icon.jpg</iconUrl>
</template>
<template type="brooklyn.demo.SimpleCouchDBCluster" name="Demo CouchDB">
<description>Deploys a demonstration CouchDB cluster</description>
<iconUrl>http://downloads.cloudsoftcorp.com/brooklyn/catalog/logos/couchdb-logo-icon.png</iconUrl>
</template>
<classpath>
<entry>http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-simple-web-cluster/${BROOKLYN_VERSION}/brooklyn-example-simple-web-cluster-${BROOKLYN_VERSION}.jar</entry>
<entry>http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-simple-nosql-cluster/${BROOKLYN_VERSION}/brooklyn-example-simple-nosql-cluster-${BROOKLYN_VERSION}.jar</entry>
</classpath>
</catalog>
EOF
log "...done!"
# Run Brooklyn
log -n "Starting Brooklyn..."
ssh -n -f ${SSH_OPTS} ${USER}@${HOST} "nohup ./brooklyn-${BROOKLYN_VERSION}/bin/brooklyn launch >> ./brooklyn-${BROOKLYN_VERSION}/brooklyn-console.log 2>&1 &"
retry "ssh ${SSH_OPTS} ${USER}@${HOST} \"test -e ./brooklyn-${BROOKLYN_VERSION}/brooklyn-console.log\""
retry "ssh ${SSH_OPTS} ${USER}@${HOST} \"grep -q \"Started Brooklyn console at\" ./brooklyn-${BROOKLYN_VERSION}/brooklyn-console.log &>/dev/null\""
log "...done!"
URL=$(ssh ${SSH_OPTS} ${USER}@${HOST} "grep 'Started Brooklyn console at' ./brooklyn-${BROOKLYN_VERSION}/brooklyn-console.log | cut -d' ' -f9 | tr -d ," | sed -e "s/127\.0\.0\.1/${HOST}/g" -e "s/0\.0\.0\.0/${HOST}/g" 2>&1)
log "Brooklyn Console URL is ${URL}"
if ${GENERATE_PASSWORD}; then
log "Brooklyn Console password for the '${USER}' user is '${PASSWORD}'"
CREDENTIALS="--user=admin --password=${PASSWORD}"
fi
log -n "Checking Brooklyn connection..."
if wget -qO- --retry-connrefused --no-check-certificate ${CREDENTIALS} ${URL} &> /dev/null; then
log "...success!"
else
fail "Cannot connect to Console URL"
fi