#!/bin/bash #Copyright (c) 2009 Eucalyptus Systems, Inc. # #This program is free software: you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation, only version 3 of the License. # #This file is distributed in the hope that it will be useful, but WITHOUT #ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License #for more details. # #You should have received a copy of the GNU General Public License along #with this program. If not, see . # #Please contact Eucalyptus Systems, Inc., 130 Castilian #Dr., Goleta, CA 93101 USA or visit #if you need additional information or have any questions. # #This file may incorporate work covered under the following copyright and #permission notice: # # Software License Agreement (BSD License) # # Copyright (c) 2008, Regents of the University of California # # # Redistribution and use of this software in source and binary forms, with # or without modification, are permitted provided that the following # conditions are met: # # Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF # THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE # LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS # SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING # IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA # BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN # THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT # OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR # WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH # ANY SUCH LICENSES OR RIGHTS. # # #FAKEREG="yes" FILE="//etc/eucalyptus/eucalyptus.conf" IMPORTFILE="" EUCALYPTUS="" CC_PORT="" NC_PORT="" CLOUD_PORT="" CLOUD_SSL_PORT="" NAME="" INSTANCE="" EUCA_USER="" HYPERVISOR="" DHCPD="" DHCP_USER="" BRIDGE="" NEWNODES="" NODEMODE="" WALRUS_MODE="" SYNC="" WALRUS="" WALRUS_MODE="" CLUSNAME="" NEWCLUS="" CLUSMODE="" UPGRADE_CONF="" SETUP="" VERSION="" CHECK="" TOSYNC="" TO_BACKUP="Y" CREDENTIALZIPFILE="" SCP="`which scp 2> /dev/null`" RSYNC="`which rsync 2> /dev/null`" WGET="`which wget 2> /dev/null`" VERBOSE="N" LIST="" ENABLED="" DISABLED="" TO_START="" usage () { echo "$0 [options] []" echo echo "where is the configuration file ($FILE by default)" echo " --help this message" echo " -d point EUCALYPTUS to " echo " --no-rsync don't use rsync" echo " --no-scp don't use scp" echo " --skip-scp-hostcheck skip scp interactive host keycheck" echo " --get-credentials download credentials to " echo " --register-nodes \"host host ...\" add new nodes to EUCALYPTUS" echo " --deregister-nodes \"host host ...\" remove nodes from EUCALYPTUS" echo " --register-cluster add new cluster to EUCALYPTUS" echo " --deregister-cluster remove cluster from EUCALYPTUS" echo " --register-walrus add walrus to EUCALYPTUS" echo " --deregister-walrus remove walrus from EUCALYPTUS" echo " --register-sc add storage controller" echo " --deregister-sc remove storage controller from EUCALYPTUS" echo " --list-walruses list registered walrus(es)" echo " --list-clusters list registered CCs" echo " --list-nodes list registered NCs" echo " --list-scs list registered SCs" echo " --no-sync used only with --register-* to skip syncing keys" echo " --cc-port set CC port" echo " --nc-port set NC port" echo " --instances set the INSTANCE path" # echo " --cloud-port set the 2 cloud ports" echo " --hypervisor set hypervisor to use" echo " --user set the user to use" echo " --dhcpd set the dhcpd binary to " echo " --dhcp_user set the username to run dhcpd as" echo " --name returns the value or " echo " --import-conf import variables from into eucalyptus.conf" echo " --setup perform initial setup" echo " --enable {cloud|walrus|sc} enable service at next start" echo " --disable {cloud|walrus|sc} disable service at next start" echo " --check {nc|cc|cloud|sc|walrus} pre-flight checks" # echo " --sync {nc|cc|cloud|sc|walrus} pre-flight checks" echo " --version eucalyptus version" echo } # utility function to make a copy of the conf file check_and_backup () { # can we write to the configuration file? if [ ! -w $1 ]; then echo "Cannot write to $1!" exit 1 fi # let's see if we need a copy if [ "$TO_BACKUP" = "Y" ]; then cp $1 $1.bak TO_BACKUP="N" fi } # 3 paramenter: the file, the variable name, the new value change_var_value () { check_and_backup $1 sed -i "s<^[[:blank:]#]*\(${2}\).*<\1=\"${3}\"<" $1 } # comment lines matching $2 ($1 is the file) comment () { check_and_backup $1 sed -i "s<^[[:blank:]]*\(${2}.*\)<#\1<" $1 } # comment lines matching $2 ($1 is the file) uncomment () { check_and_backup $1 sed -i "s<^[#[:blank:]]*\(${2}.*\)<\1<" $1 } check_heartbeat() { local __host="$1" local __service="$2" local ret="" # checks if [ -z "$__host" -o -z "$__service" ]; then echo "check_heartbeat: need a host and a service!" return 1 fi if [ -z "$WGET" -o ! -x "$WGET" ]; then echo "ERROR: wget is missing, cannot continue." return 1 fi # let's talk to the host and check if something is running ret="`$WGET -q -T 10 -t 1 -O - http://${__host}:8773/services/Heartbeat`" if [ "$?" != "0" -o -z "$ret" ]; then return 1 fi # we need both ehabled and local to be true if ! echo $ret |grep "enabled=true" > /dev/null ; then return 1 elif ! echo $ret |grep "local=true" > /dev/null ; then return 1 fi return 0 } check_ws() { local URL="$1" local ret="" local soap_error="" if [ -z "$URL" ]; then echo "check_ws: need a URL!" return 1 fi if [ -n "${FAKEREG}" ]; then ret="" elif [ "$2" != "" ]; then if [ "$VERBOSE" = "Y" ]; then echo "$WGET -q -T 10 -t 1 -O - \"$URL\"" "|sed 's/\\(.*\\)<\\/euca:registered>/\\n\\1\\n/g;s//\\n>/g;s/<\\/*euca:item>//g;s/<\\/*euca:[^>]*>/ /g'|awk -F\">\" '/>/{print \" \"$2}')" fi E=$($WGET -q -T 10 -t 1 -O - "$URL"|\ sed 's/\(.*\)<\/euca:registered>/\n\1\n/g;s//\n>/g;s/<\/*euca:item>//g;s/<\/*euca:[^>]*>/ /g'|\ awk -F">" '/>/{print " "$2}') eval "$2=\"${E}\"" else if [ "$VERBOSE" = "Y" ]; then echo "$WGET -q -T 10 -t 1 -O - \"$URL\" |grep faultstring | sed 's:.*\(.*\).*:\1:'" fi soap_error="`$WGET -q -T 10 -t 1 -O - \"$URL\"`" ret="$?" soap_error="`echo $soap_error |grep faultstring | sed 's:.*\(.*\).*:\1:'`" if test -n "$soap_error" ; then echo $soap_error ret="1" fi fi return $ret } component_sync_keys() { local COMPONENT="" local NAME="" if [ "$SYNC" = "N" ]; then return 0 fi if [ $# -lt 1 ]; then return 1 fi COMPONENT="$1" shift NAME="$2" shift if [ "$COMPONENT" = "walrus" ]; then echo "syncing walrus" elif [ "$COMPONENT" = "cc" ]; then echo "syncing cc($NAME)" elif [ "$COMPONENT" = "sc" ]; then echo "syncing sc($NAME)" elif [ "$COMPONENT" = "nc" ]; then echo "syncing nc" fi } # copy files over. sync_keys() { local SOURCEDIR="" local DESTDIR="" local REMOTE="" local FILES="" local FILE="" if [ "$SYNC" = "N" ]; then return 0 fi if [ $# -lt 4 ]; then return 1 fi SOURCEDIRS="$1" shift DESTDIR="$1" shift REMOTE="$1" shift while [ $# -ge 1 ]; do FILE="" for sd in `echo $SOURCEDIRS | sed "s/,/ /g"` do if [ -e "${sd}/${1}" ]; then FILE="${sd}/${1}" fi done if [ "$FILE" = "" ]; then echo "Warning: cannot file file ${1} in ${SOURCEDIRS}" else FILES="$FILES $FILE" fi shift done # is REMOTE actually localhost? if [ ${REMOTE} = "127.0.0.1" -o ${REMOTE} = localhost -o ${REMOTE} = "`hostname -s`" -o ${REMOTE} = "`hostname -f`" ]; then # machine is localhost, not need for remote syncing if [ -d "$SOURCEDIR" ]; then for i in $FILES do if [ ! -e $i ]; then echo "ERROR: cannot find cluster credentials." exit 1 else if ! rsync -a $i $DESTDIR ; then echo "ERROR: cannot copy file (${i}) to destination (${DESTDIR})" return 1 fi fi done else echo "ERROR: Cannot find source keys directory." return 1 fi return 0 fi # try rsync first if [ -n "$RSYNC" ]; then echo echo -n "Trying rsync to sync keys with \"${REMOTE}\"..." if $RSYNC -az ${FILES} ${REMOTE}:${DESTDIR}/ > /dev/null ; then echo "done." return 0 else echo "failed." fi fi # scp next if [ -n "$SCP" ]; then echo if [ "$EUCA_USER" = "" ]; then if getent passwd eucalyptus > /dev/null ; then echo "Using 'eucalyptus' as EUCA_USER" EUCA_USER="eucalyptus" else echo "EUCA_USER is not defined!" return 1 fi fi echo echo "Trying scp to sync keys with \"${1}\" (user \"${EUCA_USER}\")..." if sudo -u ${EUCA_USER} $SCP ${FILES} ${EUCA_USER}@${REMOTE}:${DESTDIR} > /dev/null ; then echo "done." return 0 else echo "failed." fi fi return 1 } if [ $# -eq 0 ]; then usage exit 1 fi # let's parse the command line while [ $# -gt 0 ]; do if [ "$1" = "-h" -o "$1" = "-help" -o "$1" = "?" -o "$1" = "--help" ]; then usage exit 1 fi if [ "$1" = "-synckeys" -o "$1" = "-synckey" ]; then NODEMODE="SYNC" shift continue fi if [ "$1" = "-norsync" -o "$1" = "--no-rsync" ]; then RSYNC="" shift continue fi if [ "$1" = "--list-scs" ]; then LIST="$LIST storages" shift continue fi if [ "$1" = "--list-walruses" ]; then LIST="$LIST walruses" shift continue fi if [ "$1" = "--list-clusters" ]; then LIST="$LIST clusters" shift continue fi if [ "$1" = "--list-nodes" ]; then LIST="$LIST nodes" shift continue fi if [ "$1" = "--verbose" ]; then VERBOSE="Y" shift continue fi if [ "$1" = "-noscp" -o "$1" = "--no-scp" ]; then SCP="" shift continue fi if [ "$1" = "--skip-scp-hostcheck" ]; then SCP_OPT="-oStrictHostKeyChecking=no" shift continue fi if [ "$1" = "-version" -o "$1" = "--version" ]; then VERSION="Y" shift continue fi if [ "$1" = "-setup" -o "$1" = "--setup" ]; then SETUP="Y" shift continue fi if [ "$1" = "--no-sync" ]; then SYNC="N" shift continue fi if [ "$1" = "--deregister-walrus" ]; then WALRUS_MODE="DEL" shift continue fi if [ $# -eq 1 ]; then # we dont have options with no argument, so it has to be # the file FILE="$1" if [ "${FILE:0:1}" = '-' ]; then usage exit 1 fi break fi # all other parameters requires at least 1 argument if [ $# -lt 2 ]; then usage exit 1 fi # old command line options not used anylonger if [ "$1" = "-cc" -o "$1" = "-nc" -o "$1" = "-cloud" ]; then echo "-cc, -nc and -cloud are not used anymore" shift; shift; continue fi if [ "$1" = "-d" ]; then if [ ! -d "${2}" ]; then echo "Is $2 where Eucalyptus is installed?" exit 1 fi EUCALYPTUS="${2}" shift; shift continue fi if [ "$1" = "-name" -o "$1" = "--name" ]; then NAME="$NAME $2" shift; shift continue fi if [ "$1" = "-bridge" ]; then BRIDGE="$2" shift; shift continue fi if [ "$1" = "-upgrade-conf" -o "$1" = "--upgrade-conf" ]; then # hidden options to upgrade from an older version UPGRADE_CONF="$2" if [ ! -e "$UPGRADE_CONF" ]; then echo "Cannot read $UPGRADE_CONF" exit 1 fi shift; shift continue fi if [ "$1" = "-import-conf" -o "$1" = "--import-conf" ]; then IMPORTFILE="$2" if [ ! -e "$IMPORTFILE" ]; then echo "Cannot read $IMPORTFILE" exit 1 fi shift; shift continue fi if [ "$1" = "-dhcpd" -o "$1" = "--dhcpd" ]; then DHCPD="$2" shift; shift continue fi if [ "$1" = "-dhcp_user" -o "$1" = "--dhcp_user" ]; then DHCPC_USER="$2" shift; shift continue fi if [ "$1" = "-nodes" ]; then NODES="${2}" shift; shift continue fi if [ "$1" = "-ccp" -o "$1" = "--cc-port" ]; then CC_PORT="$2" shift; shift continue fi if [ "$1" = "-ncp" -o "$1" = "--nc-port" ]; then NC_PORT="$2" shift; shift continue fi if [ "$1" = "-instances" -o "$1" = "--instances" ]; then INSTANCE="$2" shift; shift continue fi if [ "$1" = "-user" -o "$1" = "--user" ]; then EUCA_USER="$2" shift; shift continue fi if [ "$1" = "-hypervisor" -o "$1" = "--hypervisor" ]; then if [ "$2" != "xen" -a "$2" != "kvm" ]; then echo "Only kvm or xen are supported at the moment" exit 1 fi HYPERVISOR="$2" shift; shift continue fi if [ "$1" = "-cloudp" ]; then if [ $# -lt 3 ]; then echo "We need 2 ports for cloud controller" exit 1 fi # doesn't work right now # CLOUD_PORT="$2" # CLOUD_SSL_PORT="$3" shift; shift; shift continue fi if [ "$1" = "--get-credentials" ]; then CREDENTIALZIPFILE="${2}" shift; shift; continue fi if [ "$1" = "-addnode" -o "$1" = "--register-nodes" ]; then NEWNODES="${2}" NODEMODE="ADD" shift; shift continue fi if [ "$1" = "-delnode" -o "$1" = "--deregister-nodes" ]; then NEWNODES="${2}" NODEMODE="REM" shift; shift continue fi if [ "$1" = "--register-walrus" ]; then WALRUS_MODE="ADD" WALRUS="$2" shift; shift continue fi if [ "$1" = "--deregister-sc" ]; then SC_MODE="DEL" SCNAME="$2" shift; shift continue fi if [ "$1" = "--register-sc" ]; then if [ $# -lt 3 ]; then echo "--register-sc requires a CC and a hostname" exit 1 fi SC_MODE="ADD" SCNAME="$2" SCHOST="$3" shift; shift; shift continue fi if [ "$1" = "-addcluster" -o "$1" = "--register-cluster" ]; then if [ $# -lt 3 ]; then echo "--register-cluster requires a user assigned name and CC hostname" exit 1 fi CLUSNAME="$2" NEWCLUS="$3" CLUSMODE="ADD" shift; shift; shift continue fi if [ "$1" = "--deregister-cluster" ]; then CLUSNAME="$2" CLUSMODE="DEL" shift; shift continue fi if [ "$1" = "-check" -o "$1" = "--check" ]; then if [ "$2" != "cc" -a "$2" != "cloud" -a "$2" != "nc" -a "$2" != "sc" -a "$2" != "walrus" ]; then echo "-check requires cc, nc, sc, walrus or cloud" exit 1 fi CHECK="$2" shift; shift continue fi if [ "$1" = "--enable" ]; then if [ "$2" != "cloud" -a "$2" != "sc" -a "$2" != "walrus" ]; then echo "--enable requires cloud, sc or walrus" exit 1 fi ENABLED="$ENABLED $2" shift; shift continue fi if [ "$1" = "--disable" ]; then if [ "$2" != "cloud" -a "$2" != "sc" -a "$2" != "walrus" ]; then echo "--disable requires cloud, sc or walrus" exit 1 fi DISABLED="$DISABLED $2" shift; shift continue fi if [ "$1" = "-sync" -o "$1" = "--sync" ]; then if [ "$2" != "cc" -a "$2" != "cloud" -a "$2" != "nc" -a "$2" != "sc" -a "$2" != "walrus" ]; then echo "-sync requires cc, nc, sc, walrus or cloud" exit 1 fi TOSYNC="$2" shift; shift continue fi usage exit 1 done if [ -z "${FILE}" -o ! -f "${FILE}" ]; then echo "$FILE is not a valid eucalyptus configuration file" exit 1 fi # if asked to print the version that's all we do if [ "$VERSION" = "Y" ]; then . $FILE if [ -e $EUCALYPTUS/etc/eucalyptus/eucalyptus-version ]; then VERSION="$EUCALYPTUS/etc/eucalyptus/eucalyptus-version" elif [ -e //etc/eucalyptus/eucalyptus-version ]; then VERSION="//etc/eucalyptus/eucalyptus-version" fi if [ -n "$VERSION" ]; then echo -n "Eucalyptus version: " cat $VERSION else echo "Cannot find eucalyptus installation!" exit 1 fi exit 0 fi # let's change the value if [ -n "$EUCALYPTUS" ]; then change_var_value $FILE EUCALYPTUS "${EUCALYPTUS}" fi if [ -n "$CC_PORT" ]; then change_var_value $FILE CC_PORT "${CC_PORT}" fi if [ -n "$NC_PORT" ]; then change_var_value $FILE NC_PORT "${NC_PORT}" fi if [ -n "$CLOUD_PORT" ]; then change_var_value $FILE CLOUD_PORT "${CLOUD_PORT}" fi if [ -n "$CLOUD_SSL_PORT" ]; then change_var_value $FILE CLOUD_SSL_PORT "${CLOUD_SSL_PORT}" fi if [ -n "$INSTANCE" ]; then change_var_value $FILE INSTANCE_PATH "${INSTANCE}" fi if [ -n "$DHCPD" ]; then change_var_value $FILE VNET_DHCPDAEMON "${DHCPD}" fi if [ -n "$DHCPC_USER" ]; then change_var_value $FILE VNET_DHCPUSER "${DHCPC_USER}" uncomment $FILE VNET_DHCPUSER fi if [ -n "$NODES" ]; then change_var_value $FILE NODES "${NODES}" fi if [ -n "$HYPERVISOR" ]; then change_var_value $FILE HYPERVISOR "${HYPERVISOR}" uncomment $FILE HYPERVISOR fi if [ -n "$BRIDGE" ]; then change_var_value $FILE VNET_BRIDGE "${BRIDGE}" uncomment $FILE VNET_BRIDGE fi if [ -n "$EUCA_USER" ]; then ID="`which id 2> /dev/null`" if [ -n "$ID" ]; then if ! $ID $EUCA_USER > /dev/null 2> /dev/null ; then echo "WARNING: $EUCA_USER doesn't exists!" fi fi change_var_value $FILE EUCA_USER "${EUCA_USER}" fi for x in $NAME ; do VALUE=`cat $FILE |grep $x|cut -f 2 -d =|tr '"' ' '` echo "$x=$VALUE" done # modify the current conf file based on an older configuration, or from import file if [ -n "$UPGRADE_CONF" -o -n "$IMPORTFILE" ]; then VARS="EUCA_USER ENABLE_WS_SECURITY DISABLE_EBS HYPERVISOR LOGLEVEL SWAP_SIZE CC_PORT MANUAL_INSTANCES_CLEANUP NC_CACHE_SIZE SCHEDPOLICY NODES NC_SERVICE NC_PORT MAX_MEM MAX_CORES INSTANCE_PATH VNET_BRIDGE VNET_DHCPDAEMON VNET_DHCPUSER" VNET_VARS="VNET_MODE VNET_SUBNET VNET_NETMASK VNET_DNS VNET_ADDRSPERNET VNET_PUBLICIPS VNET_BROADCAST VNET_ROUTER VNET_MACMAP VNET_INTERFACE" if [ -n "$UPGRADE_CONF" ]; then # source the old config VARS_TO_DO=$VARS VNET_VARS_TO_DO=$VNET_VARS . $UPGRADE_CONF elif [ -n "$IMPORTFILE" ]; then VARS_TO_DO="" VNET_VARS_TO_DO="" . $IMPORTFILE for i in $VNET_VARS do VAL="$(echo \$${i})" eval VAL=$VAL if [ -n "$VAL" ]; then VNET_VARS_TO_DO="$VNET_VARS_TO_DO $i" fi done fi # let's start from no network for x in $VNET_VARS_TO_DO ; do comment $FILE $x done # modified the defined variables for x in $VARS_TO_DO ; do y="$(echo \$${x})" eval y="$y" if [ -z "$y" ]; then # we just leave NODES uncommented even if it's empty if [ "$x" != "NODES" ]; then comment $FILE $x fi else uncomment $FILE $x change_var_value $FILE $x "${y}" fi done # and add the network variables echo >> $FILE echo "# network configuration from the input configuration file" >> $FILE for x in $VNET_VARS_TO_DO ; do y="$(echo \$${x})" eval y="$y" if [ -n "$y" ]; then if [ "$x" = "VNET_INTERFACE" ]; then change_var_value $FILE VNET_PRIVINTERFACE "${y}" change_var_value $FILE VNET_PUBINTERFACE "${y}" else echo "$x=\"${y}\"" >> $FILE fi fi done fi # we may need the location of the ssh key for eucalyptus EUCA_HOME="`getent passwd eucalyptus|cut -f 6 -d ':'`" if [ -f "${EUCA_HOME}/.ssh/id_rsa.pub" ]; then SSHKEY=`cat ${EUCA_HOME}/.ssh/id_rsa.pub` else SSHKEY="" fi # we need defaults in eucalyptus.conf . $FILE # first time setup if [ -n "$SETUP" ]; then ROOTWRAP="$EUCALYPTUS/usr/lib/eucalyptus/euca_rootwrap" # first of all setup euca_rootwrap if [ ! -x "$ROOTWRAP" ]; then echo "Cannot find $ROOTWRAP (or not readable)!" exit 1 fi # get EUCA group if [ -z "$EUCA_USER" ]; then echo "Is EUCA_USER defined?" exit 1 fi # if running as root no need to do anything if [ "$EUCA_USER" != "root" ]; then ID="`which id 2> /dev/null`" if [ -z "$ID" ]; then echo "Cannot find command $ID" exit 1 fi if ! $ID $EUCA_USER > /dev/null 2> /dev/null ; then echo "User $EUCA_USER doesn't exists!" exit 1 fi EUCA_GROUP="`$ID -ng $EUCA_USER 2>/dev/null`" if [ -z "$EUCA_GROUP" ]; then echo "Cannot detect $EUCA_USER group" exit 1 fi if ! chown root:$EUCA_GROUP $ROOTWRAP ; then exit 1 fi if ! chmod 4750 $ROOTWRAP ; then exit 1 fi fi # let's create the instance path if [ -n "$INSTANCE_PATH" -a "$INSTANCE_PATH" != "not_configured" -a ! -d "$INSTANCE_PATH" ]; then if ! mkdir -p $INSTANCE_PATH ; then echo "Failed to create instance path!" exit 1 fi if ! chown $EUCA_USER:$EUCA_GROUP $INSTANCE_PATH ; then exit 1 fi fi chown -R $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/lib/eucalyptus ret=$? chown -R $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/log/eucalyptus let $((ret += $?)) chown -R $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/run/eucalyptus let $((ret += $?)) chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/etc/eucalyptus/eucalyptus.conf let $((ret += $?)) # let's create more needed directory with the right permissions mkdir -p $EUCALYPTUS/var/lib/eucalyptus/db let $((ret += $?)) chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/lib/eucalyptus/db let $((ret += $?)) chmod 700 $EUCALYPTUS/var/lib/eucalyptus/db let $((ret += $?)) mkdir -p $EUCALYPTUS/var/lib/eucalyptus/keys let $((ret += $?)) chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/lib/eucalyptus/keys let $((ret += $?)) chmod 700 $EUCALYPTUS/var/lib/eucalyptus/keys let $((ret += $?)) mkdir -p $EUCALYPTUS/var/lib/eucalyptus/CC let $((ret += $?)) chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/lib/eucalyptus/CC let $((ret += $?)) chmod 700 $EUCALYPTUS/var/lib/eucalyptus/CC let $((ret += $?)) exit $ret fi if [ -n "$TOSYNC" ]; then echo "not implemented" fi # pre-flight checks if [ -n "$CHECK" ]; then ROOTWRAP="$EUCALYPTUS/usr/lib/eucalyptus/euca_rootwrap" # vblade and aoe may be needed if [ "$DISABLE_EBS" != "Y" -a "$DISABLE_EBS" != "y" ]; then if [ "$CHECK" = "sc" ]; then VBLADE="`which vblade 2> /dev/null`" if [ -z "$VBLADE" ]; then echo echo "ERROR: EBS is enabled and vblade was not found" exit 1 fi fi fi # first of all check euca_rootwrap if [ ! -x $ROOTWRAP ]; then echo "Cannot find euca_rootwrap!" exit 1 fi # get EUCA group if [ -z "$EUCA_USER" ]; then echo "Running eucalyptus as root" EUCA_USER="root" EUCA_GROUP="root" fi # if running as root no need to do anything if [ "$EUCA_USER" != "root" ]; then ID="`which id 2> /dev/null`" if [ -z "$ID" ]; then echo "Cannot find command id" exit 1 fi if ! $ID $EUCA_USER > /dev/null 2> /dev/null ; then echo "User $EUCA_USER doesn't exists!" exit 1 fi EUCA_GROUP="`$ID -ng $EUCA_USER 2>/dev/null`" if [ -z "$EUCA_GROUP" ]; then echo "Cannot detect $EUCA_USER group: using $EUCA_USER" exit 1 fi # need to check if euca_rootwrap can run as EUCA_USER TEST_EUID="`sudo -u $EUCA_USER $ROOTWRAP $ID -u`" if [ "$?" != "0" -o "$TEST_EUID" != "0" ]; then echo "Problem running $ROOTWRAP! Did you run euca_conf -setup?" exit 1 fi fi # let's be sure we have the INSTANCE_PATH if [ "$CHECK" = "nc" ]; then if [ -z "$INSTANCE_PATH" ]; then echo "INSTANCE_PATH is not defined" exit 1 fi if [ ! -d "$INSTANCE_PATH" ]; then echo "$INSTANCE_PATH doesn't exist: did you run euca_conf -setup?" exit 1 fi fi # let's set up directories which could disappears if /var/run is # in memory if [ ! -d $EUCALYPTUS/var/run/eucalyptus ]; then if ! mkdir -p $EUCALYPTUS/var/run/eucalyptus ; then # error should come from mkdir exit 1 fi fi if ! chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/run/eucalyptus ; then # error should come from chown exit 1 fi if [ "$CHECK" = "cc" ]; then if [ ! -d $EUCALYPTUS/var/run/eucalyptus/net ]; then if ! mkdir -p $EUCALYPTUS/var/run/eucalyptus/net ; then # error should come from mkdir exit 1 fi fi if ! chown $EUCA_USER:$EUCA_GROUP $EUCALYPTUS/var/run/eucalyptus/net ; then # error should come from chown exit 1 fi fi # good to go exit 0 fi createCloudURL () { if ! getSecretKey; then echo "ERROR: cannot get credentials" return 1 fi ARGS="AWSAccessKeyId=$AKEY" KEY=$1 shift VAL=$1 shift while ( test -n "$KEY" -a -n "$VAL") do ARGS="${ARGS}&${KEY}=${VAL}" KEY=$1 shift VAL=$1 shift done if [ -z "$SKEY" ]; then echo "ERROR: SKEY parameter is not set." export URL="" return 1 fi ARGS="${ARGS}&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=$(date -u '+%Y-%m-%dT%H%%3A%M%%3A%S.000Z')&Version=eucalyptus" SIGNATURE=$(echo -en "GET\n127.0.0.1\n/services/Configuration\n${ARGS}" | openssl dgst -sha256 -hmac ${SKEY} -binary | openssl base64) export URL="http://127.0.0.1:8773/services/Configuration?${ARGS}&Signature=${SIGNATURE}" if [ "$VERBOSE" = "Y" ]; then echo $URL fi return 0 } getSecretKey() { if [ -d "$EUCALYPTUS/var/lib/eucalyptus/db/" ]; then DBDIR="$EUCALYPTUS/var/lib/eucalyptus/db/" else echo "ERROR: cannot locate eucalyptus database, try logging in through the admin web interface." exit 1 fi FIELD=`grep -i "CREATE .*TABLE AUTH_USERS" ${DBDIR}/*auth* | sed 's/,/\n/g' | awk '/[Uu][Ss][Ee][Rr]_[Ss][Ee][Cc][Rr][Ee][Tt][Kk][Ee][Yy]/ {print NR}'` if [ "$FIELD" = "" ]; then echo "ERROR: cannot locate entry in eucalyptus database, try logging in through the admin web interface" export SKEY="" return 1 fi SKEY=$(eval echo $(awk -v field=${FIELD} -F, '/INSERT INTO AUTH_USERS.*admin/ {print $field}' ${DBDIR}/*auth* | head -n 1)) FIELD=`grep -i "CREATE .*TABLE AUTH_USERS" ${DBDIR}/*auth* | sed 's/,/\n/g' | awk '/[Uu][Ss][Ee][Rr]_[Qq][Uu][Ee][Rr][Yy]_[Ii][Dd]/ {print NR}'` if [ "$FIELD" = "" ]; then echo "ERROR: cannot locate entry in eucalyptus database, try logging in through the admin web interface" export AKEY="" return 1 fi AKEY=$(eval echo $(awk -v field=${FIELD} -F, '/INSERT INTO AUTH_USERS.*admin/ {print $field}' ${DBDIR}/*auth* | head -n 1)) return 0 } checkLocalService() { local SERVICE="" if [ -z "$WGET" -o ! -x "$WGET" ]; then echo "ERROR: wget is missing, cannot continue." return 1 fi SERVICE="$1" if [ -z "$SERVICE" ]; then echo "ERROR: must pass in service name (CLC, CC)" return 1 elif [ "$SERVICE" = "CLC" ]; then if [ -n "$FAKEREG" ]; then local SOURCEDIR="$EUCALYPTUS/var/lib/eucalyptus/keys/" for i in cloud do if [ ! -e "$SOURCEDIR/${i}-cert.pem" -o ! -e "$SOURCEDIR/${i}-pk.pem" ]; then openssl req -new -nodes -x509 -out $SOURCEDIR/${i}-cert.pem -keyout $SOURCEDIR/${i}-pk.pem -days 365 -subj "/C=US/ST=CA/L=City/CN=localhost/emailAddress=root@localhost" fi done fi CMD="$WGET -T 10 -t 1 -O - -q --no-check-certificate https://127.0.0.1:8443/register | grep CloudVersion >/dev/null" elif [ "$SERVICE" = "CC" ]; then CMD="$WGET -T 10 -t 1 -O - -q http://127.0.0.1:8774/axis2/services/ | grep EucalyptusCC >/dev/null" fi if [ -n "${FAKEREG}" ]; then CMD="echo" fi if ! eval $CMD ; then echo "ERROR: you need to be on the $SERVICE host and the $SERVICE needs to be running." return 1 fi return 0 } if [ -n "$CREDENTIALZIPFILE" ]; then if [ -f "$CREDENTIALZIPFILE" ]; then echo "file '$CREDENTIALZIPFILE' already exists, please remove and try again" exit 1 fi if ! checkLocalService "CLC" ; then exit 1 fi if [ -d "$EUCALYPTUS/var/lib/eucalyptus/db/" ]; then DBDIR="$EUCALYPTUS/var/lib/eucalyptus/db/" else echo "ERROR: cannot locate eucalyptus database, try logging in through the admin web interface." exit 1 fi FIELD=`grep -i "CREATE .*TABLE USERS" ${DBDIR}/* | sed 's/,/\n/g' | awk '/[Uu][Ss][Ee][Rr]_[Cc][Ee][Rr][Tt][Ii][Ff][Ii][Cc][Aa][Tt][Ee]_[Cc][Oo][Dd][Ee]/ {print NR}'` if [ -z "$FIELD" ]; then echo "cannot find code field in database, please go to the Eucalyptus web UI to obtain credentials." exit 1 fi KEY=$(eval echo $(awk -v field=${FIELD} -F, '/INSERT INTO USERS.*admin/ {print $field}' ${DBDIR}/* | head -n 1)) if [ -z "$KEY" ]; then echo "cannot find code in database, please go to the Eucalyptus web UI to obtain credentials." exit 1 fi CMD="$WGET --no-check-certificate \"https://localhost:8443/getX509?user=admin&code=$KEY\" -O $CREDENTIALZIPFILE" if ! eval $CMD ; then echo "failed to obtain credentals, please try again or go to the Eucalyptus web UI." exit 1 fi fi # adding a new cluster if [ -n "$CLUSNAME" ]; then if ! checkLocalService "CLC" ; then exit 1 fi if [ "$CLUSMODE" = "ADD" ]; then if [ -d "${EUCALYPTUS}/var/lib/eucalyptus/keys/" ]; then SOURCEDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/${CLUSNAME}/ DESTDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ else echo "ERROR: cannot find key directory ($EUCALYPTUS/var/lib/eucalyptus/keys), check that your installation was successful!" exit 1 fi URL="" if ! createCloudURL "Action" "RegisterCluster" "Host" "${NEWCLUS}" "Name" "${CLUSNAME}" "Port" "${CC_PORT}"; then exit 1 fi if ! check_ws "$URL" ; then echo "ERROR: failed to register new cluster, please log in to the admin interface and check cloud status." exit 1 fi if [ -n "${FAKEREG}" ]; then mkdir -p $SOURCEDIR if [ -n "${FAKEREG}" ]; then mkdir -p $SOURCEDIR for i in cluster node do if [ ! -e "$SOURCEDIR/${i}-cert.pem" -o ! -e "$SOURCEDIR/${i}-pk.pem" ]; then openssl req -new -nodes -x509 -out $SOURCEDIR/${i}-cert.pem -keyout $SOURCEDIR/${i}-pk.pem -days 365 -subj "/C=US/ST=CA/L=City/CN=localhost/emailAddress=root@localhost" fi done fi fi # sync the keys if ! sync_keys "${DESTDIR},${SOURCEDIR}" ${DESTDIR} ${NEWCLUS} node-cert.pem cluster-cert.pem cluster-pk.pem node-pk.pem vtunpass cloud-cert.pem; then echo "ERROR: failed to sync keys with ${NEWCLUS}; registration will not be complete until keys can be synced, please try again." exit 1 fi echo echo "SUCCESS: new cluster '${CLUSNAME}' on host '${NEWCLUS}' successfully registered." elif [ "$CLUSMODE" = "DEL" ]; then URL="" # let's see if we have such a cluster LIST_RES="" if ! createCloudURL "Action" "DescribeClusters" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then echo "ERROR: cannot talk with CLC" exit 1 fi FOUND="N" for x in $LIST_RES ; do if [ "$x" = "${CLUSNAME}" ]; then FOUND="Y" break fi done if [ "$FOUND" = "N" ]; then echo "No registered cluster $CLUSNAME was found" exit 1 fi # now let's deregister URL="" if ! createCloudURL "Action" "DeregisterCluster" "Name" "${CLUSNAME}"; then exit 1 fi if ! check_ws "$URL" ; then echo "ERROR: failed to deregister new cluster, please log in to the admin interface and check cloud status." exit 1 fi echo echo "SUCCESS: cluster '${CLUSNAME}' successfully deregistered." fi fi # walrus if [ -n "$WALRUS" -o -n "$WALRUS_MODE" ]; then if ! checkLocalService "CLC" ; then exit 1 fi if [ "$WALRUS_MODE" = "ADD" ]; then echo "Adding WALRUS host $WALRUS" if [ -d "${EUCALYPTUS}/var/lib/eucalyptus/keys/" ]; then SOURCEDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ DESTDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ else echo "ERROR: cannot find key directory ($EUCALYPTUS/var/lib/eucalyptus/keys), check that your installation was successful!" exit 1 fi URL="" if ! createCloudURL "Action" "RegisterWalrus" "Host" "${WALRUS}" "Name" "walrus" "Port" "8773"; then exit 1 fi if ! check_ws "$URL" ; then echo "ERROR: failed to register Walrus, please log in to the admin interface and check cloud status." exit 1 fi # check that walrus is at least running on the remote host sleep 3 if ! check_heartbeat ${WALRUS} walrus ; then echo "WARNING: Walrus is not up on host ${WALRUS}; registration will not be complete until walrus is running." fi # sync the keys if ! sync_keys ${SOURCEDIR} ${DESTDIR} ${WALRUS} euca.p12 ; then echo "ERROR: failed to sync keys with ${WALRUS}; registration will not be complete until keys can be synced, please try again." exit 1 fi echo echo "SUCCESS: new walrus on host '${WALRUS}' successfully registered." elif [ "$WALRUS_MODE" = "DEL" ]; then URL="" if ! createCloudURL "Action" "DeregisterWalrus" "Name" "walrus"; then exit 1 fi if ! check_ws "$URL" ; then echo "ERROR: failed to deregister Walrus, please log in to the admin interface and check cloud status." exit 1 fi echo echo "SUCCESS: Walrus successfully deregistered." fi fi # sc if [ -n "$SCNAME" ]; then if ! checkLocalService "CLC" ; then exit 1 fi if [ "$SC_MODE" = "ADD" ]; then echo "Adding SC $SCHOST to cluster $SCNAME" if [ -d "${EUCALYPTUS}/var/lib/eucalyptus/keys/" ]; then SOURCEDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ DESTDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ else echo "ERROR: cannot find key directory ($EUCALYPTUS/var/lib/eucalyptus/keys), check that your installation was successful!" exit 1 fi URL="" if ! createCloudURL "Action" "RegisterStorageController" "Host" "${SCHOST}" "Name" "${SCNAME}" "Port" "8773"; then exit 1 fi if ! check_ws "$URL"; then echo "ERROR: failed to register storage controller, please log in to the admin interface and check cloud status." exit 1 fi if [ -n "${FAKEREG}" ]; then mkdir -p $SOURCEDIR for i in sc do if [ ! -e "$SOURCEDIR/${i}-cert.pem" -o ! -e "$SOURCEDIR/${i}-pk.pem" ]; then openssl req -new -nodes -x509 -out $SOURCEDIR/${i}-cert.pem -keyout $SOURCEDIR/${i}-pk.pem -days 365 -subj "/C=US/ST=CA/L=City/CN=localhost/emailAddress=root@localhost" fi done fi # sync the keys if ! sync_keys ${SOURCEDIR} ${DESTDIR} ${SCHOST} euca.p12; then echo "ERROR: failed to sync keys with ${SCHOST}; registration will not be complete until keys can be synced, please try again." exit 1 fi echo echo "SUCCESS: new SC for cluster '${SCNAME}' on host '${SCHOST}' successfully registered." elif [ "$SC_MODE" = "DEL" ]; then # let's see if we have such a storage controller LIST_RES="" if ! createCloudURL "Action" "DescribeStorageControllers" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then echo "ERROR: cannot talk with CLC" exit 1 fi FOUND="N" for x in $LIST_RES ; do if [ "$x" = "${SCNAME}" ]; then FOUND="Y" break fi done if [ "$FOUND" = "N" ]; then echo "No registered storage controller $SCNAME was found" exit 1 fi # now let's deregister URL="" if ! createCloudURL "Action" "DeregisterStorageController" "Name" "${SCNAME}"; then exit 1 fi if ! check_ws "$URL" ; then echo "ERROR: failed to deregister StorageController, please log in to the admin interface and check cloud status." exit 1 fi echo echo "SUCCESS: Storage controller for cluster '${SCNAME}' successfully deregistered." fi fi # operations on the nodes if [ -n "$NODEMODE" ]; then # for synckey we fake addnodes if [ "$NODEMODE" = "SYNC" ]; then if [ -z "$NODES" ]; then echo "Warning: there are no NODES configured" else NEWNODES="${NODES}" NODEMODE="ADD" fi fi # check we have a valid command if [ "$NODEMODE" != "ADD" -a "$NODEMODE" != "REM" ]; then echo "ERROR: unknown mode '$NODEMODE', don't know what to do" exit 1 fi if [ -d "${EUCALYPTUS}/var/lib/eucalyptus/keys/" ]; then SOURCEDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ DESTDIR=${EUCALYPTUS}/var/lib/eucalyptus/keys/ else echo "ERROR: cannot find key directory ($EUCALYPTUS/var/lib/eucalyptus/keys), check that your installation was successful and that this cluster is already registered!" exit 1 fi # CC needs to be running if ! checkLocalService "CC" ; then exit 1 fi # warn the user on where we expect the keys to be if [ "$NODEMODE" = "ADD" ]; then echo echo "INFO: We expect all nodes to have eucalyptus installed in $EUCALYPTUS for key synchronization." fi # adding (or removing) nodes for NEWNODE in ${NEWNODES} ; do # remove is simpler: just remove the node name if [ "$NODEMODE" = "REM" ]; then if ! echo "$NODES"|grep "${NEWNODE}" > /dev/null ; then echo "Node ${NEWNODE} is not known" continue fi NODES="`echo $NODES|sed \"s/${NEWNODE}//\"|tr -s ' '`" change_var_value $FILE NODES "${NODES}" echo "SUCCESS: removed node '${NEWNODE}' from '$FILE'" continue fi # let's sync keys with the nodes if ! sync_keys ${SOURCEDIR} ${DESTDIR} ${NEWNODE} node-cert.pem cluster-cert.pem node-pk.pem cloud-cert.pem; then echo echo "ERROR: could not synchronize keys with $NEWNODE!" echo "The configuration will not have this node." if [ "$SSHKEY" = "" ]; then echo "User $EUCA_USER may have to run ssh-keygen!" else echo "Hint: to setup passwordless login to the nodes as user $EUCA_USER, you can" echo "run the following commands on node $NEWNODE:" echo "sudo -u $EUCA_USER mkdir -p ~${EUCA_USER}/.ssh" echo "sudo -u $EUCA_USER tee ~${EUCA_USER}/.ssh/authorized_keys > /dev/null < /dev/null ; then # node is not present: we need to add it NODES="${NODES} $NEWNODE" change_var_value $FILE NODES "${NODES}" fi done fi for x in $LIST ; do LIST_RES="" if [ "$x" = "walruses" ]; then if ! createCloudURL "Action" "DescribeWalruses" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then exit 1 fi if [ -n "$LIST_RES" ]; then echo "registered walruses:" fi echo "$LIST_RES" fi if [ "$x" = "storages" ]; then if ! createCloudURL "Action" "DescribeStorageControllers" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then exit 1 fi if [ -n "$LIST_RES" ]; then echo "registered storage controllers:" fi echo "$LIST_RES" fi if [ "$x" = "clusters" ]; then if ! createCloudURL "Action" "DescribeClusters" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then exit 1 fi if [ -n "$LIST_RES" ]; then echo "registered clusters:" fi echo "$LIST_RES" fi if [ "$x" = "nodes" ]; then if ! createCloudURL "Action" "DescribeNodes" ; then exit 1 fi if ! check_ws "$URL" LIST_RES ; then exit 1 fi if [ -n "$LIST_RES" ]; then echo "registered nodes:" fi echo "$LIST_RES" fi done # enable/disable services if [ -r $EUCALYPTUS/var/lib/eucalyptus/services ]; then for x in `cat $EUCALYPTUS/var/lib/eucalyptus/services` ; do TO_START="$TO_START $x" done fi if [ -n "$DISABLED" -o -n "$ENABLED" ]; then for x in $TO_START $ENABLED ; do to_start="Y" for y in $DISABLED ; do if [ "$x" = "$y" ]; then to_start="N" fi done [ $to_start = "Y" ] && echo $x done | sort | uniq > $EUCALYPTUS/var/lib/eucalyptus/services fi