crowbar/crowbar-core

View on GitHub
chef/cookbooks/provisioner/templates/default/crowbar_join.ubuntu.sh.erb

Summary

Maintainability
Test Coverage
#!/bin/bash
# Copyright 2011, Dell
#
# 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.
#

case $1 in
    stop) exit 0;;
    status) bluepill chef-client status ; exit $? ;;
    start|'') : ;;
    *) echo "Unknown action to crowbar_join.sh."
        exit 1;;
esac

if [[ $TERM != screen ]]; then
    echo "Running $0 under screen.  Attach with screen -r -S crowbar-join" >&2
    exec screen -d -m -S crowbar-join "$0"
fi

if [[ ! -d /var/log/crowbar/crowbar_join ]] ; then
  mkdir -p /var/log/crowbar/crowbar_join/
fi

exec 2>>/var/log/crowbar/crowbar_join/errlog

export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): '
export DEBIAN_FRONTEND=noninteractive
set -x

if [[ -f /etc/crowbar.install.key ]]; then
    export CROWBAR_KEY="$(cat /etc/crowbar.install.key)"
fi

# Run a command and log its output.
log_to() {
    # $1 = install log to log to
    # $@ = rest of args
    local __log="/var/log/crowbar/crowbar_join/$1"
    local __timestamp="$(date '+%F %T %z')"
    shift
    printf "\n%s\n" "$__timestamp: Running $*" | \
        tee -a "$__log.err" >> "$__log.log"
    local _ret=0
    if "$@" 2>> "$__log.err" >>"$__log.log"; then
        _ret=0
    else
        _ret="$?"
        echo "$__timestamp: $* failed."
        echo "See $__log.log and $__log.err for more information."
    fi
    printf "\n$s\n--------\n"  "$(date '+%F %T %z'): Done $*" | \
        tee -a "$__log.err" >> "$__log.log"
    return $_ret
}

post_state() {
  local curlargs=(-o /dev/null --connect-timeout 60 -s \
      -L -X POST --data-binary "{ \"name\": \"$1\", \"state\": \"$2\" }" \
      -H "Accept: application/json" -H "Content-Type: application/json" \
      --max-time 240 --insecure --location)
  [[ $CROWBAR_KEY ]] && curlargs+=(-u "$CROWBAR_KEY" --digest --anyauth)
  oldumask=`umask`
  umask 077
  curl "${curlargs[@]}" "http://<%=@admin_ip%>/crowbar/crowbar/1.0/transition/default"
  umask $oldumask
}

# Spin while we wait for the interface to come up.

echo "Waiting on our network interface to come up..."
while ! ip addr | grep -v " lo" | grep -q "inet "
do
  sleep 1
done

# Get our hostname
HOSTNAME=$(hostname -f)

sync_time() {
    # stop ntpd before we run ntpdate, and start it again afterwards.
    service ntp stop
    killall ntpd
    while ! /usr/sbin/ntpdate -b <%=@admin_ip%>; do
        echo "Waiting for NTP server"
        sleep 1
    done
}

# Clean up install droppings
rm -f /update_system2.sh
rm -f /net-post-install.sh

echo "Synchronizing time (pass 1)"
sync_time

# Mark us as readying, and get our cert.
post_state $HOSTNAME "readying"
final_state="ready"
mkdir -p /etc/chef
wget -q "<%=@provisioner_web%>/validation.pem" -O- > /etc/chef/validation.pem

if [[ ! -x /etc/init.d/bluepill ]]; then
    # Install Chef
    echo "Installing Chef..."
    echo "chef chef/chef_server_url string http://<%=@admin_ip%>:4000" >/tmp/debsel.conf

    while ! log_to apt /usr/bin/apt-get update ; do
        echo "Failed to apt-get update, wait and try again"
        sleep 1
    done
    log_to apt /usr/bin/debconf-set-selections /tmp/debsel.conf
    while ! log_to apt /usr/bin/apt-get --force-yes -y install \
        chef libxml2-dev zlib1g-dev tcpdump; do
        echo "Failed to apt-get install, wait and try again"
        sleep 1
    done

    # Disable the chef-client service and make it not executable.
    log_to chef service chef-client stop
    log_to chef killall chef-client
    log_to chef update-rc.d chef-client disable
    log_to chef chmod ugo-x /etc/init.d/chef-client

    mkdir -p /opt/dell/
    (   cd /opt/dell
        wget -q "<%=@provisioner_web%>/patches.tar.gz"
        tar xzvf patches.tar.gz
        cd patches
        ./patch.sh
    )

    # Make rubygems do what we want.
    cat >/etc/gemrc <<EOF
:sources:
- <%=@provisioner_web%>/gemsite/
gem: --no-ri --no-rdoc --bindir /usr/local/bin
EOF
    gem install xml-simple
    gem install libxml-ruby
    gem install wsman
    gem install cstruct
    gem install bluepill
    mkdir -p /etc/bluepill
    curl -o /etc/bluepill/chef-client.pill <%=@provisioner_web%>/chef-client.pill
    # Create an init script for bluepill
    cat > /etc/init.d/bluepill <<EOF
#!/bin/bash
# chkconfig: 2345 99 01
# description: Bluepill Daemon runner
PATH=$PATH:/usr/local/bin:/usr/local/sbin
case \$1 in
    start) for pill in /etc/bluepill/*.pill; do
              [[ -f \$pill ]] || continue
              bluepill load "\$pill"
           done;;
    stop) echo "Stop is not implemented, since bluepill processes are run independently.";;
    status) if pidof bluepilld; then
             echo "Bluepill is running."
             exit 0
            else
             echo "Bluepill is not running."
             exit 1
            fi;;
    *) echo "\$1: Not supported.";;
esac
EOF
    chmod 755 /etc/init.d/bluepill
fi


# Run Chef
echo "Syncing time (pass 2)"
sync_time

# Until we arrange for the network to transisiton from using
# DHCP somewhere else, the first run of chef-client will always die due to
# the networking barclamp changing the IP address from dhcp to static.
# We will try to pick up and run with it.
echo "Running Chef Client  (pass 1)"
log_to chef chef-client

# Make sure our interfaces are as up as we can get them
echo "Ensuring that our network interfaces are up."
log_to ifup ifup -a

# Only transition to problem state if the second run fails.
echo "Running Chef Client (pass 2)"
if ! log_to chef chef-client ; then
    log_to ifup ifup -a
    post_state $HOSTNAME "recovering"
    echo "Error Path"
    echo "Syncing Time (pass 3)"
    sync_time
    echo "Removing Chef Cache"
    rm -rf /var/cache/chef/*
    echo "Checking Install Integrity"
    log_to apt /usr/bin/apt-get -q --force-yes -y install
    echo "Running Chef Client (pass 3) - apt/cache cleanup"
    if ! log_to chef chef-client ; then
        log_to ifup ifup -a
        echo "Error Path"
        echo "Syncing Time (pass 4)"
        sync_time
        echo "Removing Chef Cache"
        rm -rf /var/cache/chef/*
        echo "Checking Install Integrity"
        log_to apt /usr/bin/apt-get -q --force-yes -y install
        echo "Checking Keys"
        rm -f /etc/chef/client.pem
        post_state $HOSTNAME "installed"
        echo "Running Chef Client (pass 4) - password cleanup"
        if ! log_to chef chef-client ; then
            log_to ifup ifup -a
            echo "chef-client run failed four times, giving up."
            echo "Failed"
            printf "Our IP address is: %s\n" "$(ip addr show)"
            final_state="problem"
        else
            post_state "$HOSTNAME" "$final_state"
            log_to chef chef-client
        fi
    fi
fi

# Make sure our code is up to date
log_to apt apt-get -q --force-yes -y upgrade

log_to time service ntp start

# Fire up bluepill, and let it keep chef-client up.
service bluepill start

# Transition to our final state
post_state $HOSTNAME "$final_state"

echo "Done"