functions |
|
|---|---|
|
functions - Common functions used by DevStack components The following variables are assumed to be defined by certain functions: ENABLED_SERVICES EROR_ON_CLONE FILES GLANCE_HOSTPORT OFFLINE PIP_DOWNLOAD_CACHE PIP_USE_MIRRORS RECLONE TRACK_DEPENDS http_proxy, https_proxy, no_proxy |
|
|
Save trace setting |
XTRACE=$(set +o | grep xtrace)
set +o xtrace
|
|
Exit 0 if address is in network or 1 if address is not in network or netaddr library is not installed. address_in_net ip-address ip-range |
function address_in_net() {
python -c "
import netaddr
import sys
sys.exit(netaddr.IPAddress('$1') not in netaddr.IPNetwork('$2'))
"
}
|
|
Wrapper for apt-get to set cache and proxy environment variables Uses globals OFFLINE, ``*_proxy` apt_get operation package [package ...] |
function apt_get() {
[[ "$OFFLINE" = "True" || -z "$@" ]] && return
local sudo="sudo"
[[ "$(id -u)" = "0" ]] && sudo="env"
$sudo DEBIAN_FRONTEND=noninteractive \
http_proxy=$http_proxy https_proxy=$https_proxy \
no_proxy=$no_proxy \
apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
}
|
|
Gracefully cp only if source file/dir exists cp_it source destination |
function cp_it {
if [ -e $1 ] || [ -d $1 ]; then
cp -pRL $1 $2
fi
}
|
|
Prints "message" and exits die "message" |
function die() {
local exitcode=$?
set +o xtrace
echo $@
exit $exitcode
}
|
|
Checks an environment variable is not set or has length 0 OR if the exit code is non-zero and prints "message" and exits NOTE: env-var is the variable name without a '$' die_if_not_set env-var "message" |
function die_if_not_set() {
(
local exitcode=$?
set +o xtrace
local evar=$1; shift
if ! is_set $evar || [ $exitcode != 0 ]; then
echo $@
exit -1
fi
)
}
|
|
HTTP and HTTPS proxy servers are supported via the usual environment variables [1] http_proxy, https_proxy and no_proxy. They can be set in localrc or on the command line if necessary: [1] http://www.w3.org/Daemon/User/Proxies/ProxyClients.html http_proxy=http://proxy.example.com:3128/ no_proxy=repo.example.net ./stack.sh |
function export_proxy_variables() {
if [[ -n "$http_proxy" ]]; then
export http_proxy=$http_proxy
fi
if [[ -n "$https_proxy" ]]; then
export https_proxy=$https_proxy
fi
if [[ -n "$no_proxy" ]]; then
export no_proxy=$no_proxy
fi
}
|
|
Grab a numbered field from python prettytable output Fields are numbered starting with 1 Reverse syntax is supported: -1 is the last field, -2 is second to last, etc. get_field field-number |
function get_field() {
while read data; do
if [ "$1" -lt 0 ]; then
field="(\$(NF$1))"
else
field="\$$(($1 + 1))"
fi
echo "$data" | awk -F'[ \t]*\\|[ \t]*' "{print $field}"
done
}
|
|
get_packages() collects a list of package names of any type from the prerequisite files in files/{apts|rpms}. The list is intended to be passed to a package installer such as apt or yum. Only packages required for the services in ENABLED_SERVICES will be included. Two bits of metadata are recognized in the prerequisite files: - # NOPRIME defers installation to be performed later in stack.sh - # dist:DISTRO or dist:DISTRO1,DISTRO2 limits the selection of the package to the distros listed. The distro names are case insensitive. Uses globals ENABLED_SERVICES get_packages dir |
function get_packages() {
local package_dir=$1
local file_to_parse
local service
if [[ -z "$package_dir" ]]; then
echo "No package directory supplied"
return 1
fi
if [[ -z "$DISTRO" ]]; then
GetDistro
fi
for service in general ${ENABLED_SERVICES//,/ }; do
|
|
Allow individual services to specify dependencies |
if [[ -e ${package_dir}/${service} ]]; then
file_to_parse="${file_to_parse} $service"
fi
|
|
NOTE(sdague) n-api needs glance for now because that's where glance client is |
if [[ $service == n-api ]]; then
if [[ ! $file_to_parse =~ nova ]]; then
file_to_parse="${file_to_parse} nova"
fi
if [[ ! $file_to_parse =~ glance ]]; then
file_to_parse="${file_to_parse} glance"
fi
elif [[ $service == c-* ]]; then
if [[ ! $file_to_parse =~ cinder ]]; then
file_to_parse="${file_to_parse} cinder"
fi
elif [[ $service == ceilometer-* ]]; then
if [[ ! $file_to_parse =~ ceilometer ]]; then
file_to_parse="${file_to_parse} ceilometer"
fi
elif [[ $service == n-* ]]; then
if [[ ! $file_to_parse =~ nova ]]; then
file_to_parse="${file_to_parse} nova"
fi
elif [[ $service == g-* ]]; then
if [[ ! $file_to_parse =~ glance ]]; then
file_to_parse="${file_to_parse} glance"
fi
elif [[ $service == key* ]]; then
if [[ ! $file_to_parse =~ keystone ]]; then
file_to_parse="${file_to_parse} keystone"
fi
elif [[ $service == q-* ]]; then
if [[ ! $file_to_parse =~ quantum ]]; then
file_to_parse="${file_to_parse} quantum"
fi
fi
done
for file in ${file_to_parse}; do
local fname=${package_dir}/${file}
local OIFS line package distros distro
[[ -e $fname ]] || continue
OIFS=$IFS
IFS=$'\n'
for line in $(<${fname}); do
if [[ $line =~ "NOPRIME" ]]; then
continue
fi
if [[ $line =~ (.*)#.*dist:([^ ]*) ]]; then
|
|
We are using BASH regexp matching feature. |
package=${BASH_REMATCH[1]}
distros=${BASH_REMATCH[2]}
|
|
In bash ${VAR,,} will lowecase VAR |
[[ ${distros,,} =~ ${DISTRO,,} ]] && echo $package
continue
fi
echo ${line%#*}
done
IFS=$OIFS
done
}
|
|
Determine OS Vendor, Release and Update Tested with OS/X, Ubuntu, RedHat, CentOS, Fedora Returns results in global variables: os_VENDOR - vendor name os_RELEASE - release os_UPDATE - update os_PACKAGE - package type os_CODENAME - vendor's codename for release GetOSVersion |
GetOSVersion() {
|
|
Figure out which vendor we are |
if [[ -n "`which sw_vers 2>/dev/null`" ]]; then
|
|
OS/X |
os_VENDOR=`sw_vers -productName`
os_RELEASE=`sw_vers -productVersion`
os_UPDATE=${os_RELEASE##*.}
os_RELEASE=${os_RELEASE%.*}
os_PACKAGE=""
if [[ "$os_RELEASE" =~ "10.7" ]]; then
os_CODENAME="lion"
elif [[ "$os_RELEASE" =~ "10.6" ]]; then
os_CODENAME="snow leopard"
elif [[ "$os_RELEASE" =~ "10.5" ]]; then
os_CODENAME="leopard"
elif [[ "$os_RELEASE" =~ "10.4" ]]; then
os_CODENAME="tiger"
elif [[ "$os_RELEASE" =~ "10.3" ]]; then
os_CODENAME="panther"
else
os_CODENAME=""
fi
elif [[ -x $(which lsb_release 2>/dev/null) ]]; then
os_VENDOR=$(lsb_release -i -s)
os_RELEASE=$(lsb_release -r -s)
os_UPDATE=""
os_PACKAGE="rpm"
if [[ "Debian,Ubuntu" =~ $os_VENDOR ]]; then
os_PACKAGE="deb"
elif [[ "SUSE LINUX" =~ $os_VENDOR ]]; then
lsb_release -d -s | grep -q openSUSE
if [[ $? -eq 0 ]]; then
os_VENDOR="openSUSE"
fi
elif [[ $os_VENDOR =~ Red.*Hat ]]; then
os_VENDOR="Red Hat"
fi
os_CODENAME=$(lsb_release -c -s)
elif [[ -r /etc/redhat-release ]]; then
|
|
Red Hat Enterprise Linux Server release 5.5 (Tikanga) CentOS release 5.5 (Final) CentOS Linux release 6.0 (Final) Fedora release 16 (Verne) |
os_CODENAME=""
for r in "Red Hat" CentOS Fedora; do
os_VENDOR=$r
if [[ -n "`grep \"$r\" /etc/redhat-release`" ]]; then
ver=`sed -e 's/^.* \(.*\) (\(.*\)).*$/\1\|\2/' /etc/redhat-release`
os_CODENAME=${ver#*|}
os_RELEASE=${ver%|*}
os_UPDATE=${os_RELEASE##*.}
os_RELEASE=${os_RELEASE%.*}
break
fi
os_VENDOR=""
done
os_PACKAGE="rpm"
elif [[ -r /etc/SuSE-release ]]; then
for r in openSUSE "SUSE Linux"; do
if [[ "$r" = "SUSE Linux" ]]; then
os_VENDOR="SUSE LINUX"
else
os_VENDOR=$r
fi
if [[ -n "`grep \"$r\" /etc/SuSE-release`" ]]; then
os_CODENAME=`grep "CODENAME = " /etc/SuSE-release | sed 's:.* = ::g'`
os_RELEASE=`grep "VERSION = " /etc/SuSE-release | sed 's:.* = ::g'`
os_UPDATE=`grep "PATCHLEVEL = " /etc/SuSE-release | sed 's:.* = ::g'`
break
fi
os_VENDOR=""
done
os_PACKAGE="rpm"
fi
export os_VENDOR os_RELEASE os_UPDATE os_PACKAGE os_CODENAME
}
|
|
git update using reference as a branch. git_update_branch ref |
function git_update_branch() {
GIT_BRANCH=$1
git checkout -f origin/$GIT_BRANCH
|
|
a local branch might not exist |
git branch -D $GIT_BRANCH || true
git checkout -b $GIT_BRANCH
}
|
|
git update using reference as a tag. Be careful editing source at that repo as working copy will be in a detached mode git_update_tag ref |
function git_update_tag() {
GIT_TAG=$1
git tag -d $GIT_TAG
|
|
fetching given tag only |
git fetch origin tag $GIT_TAG
git checkout -f $GIT_TAG
}
|
|
git update using reference as a branch. git_update_remote_branch ref |
function git_update_remote_branch() {
GIT_BRANCH=$1
git checkout -b $GIT_BRANCH -t origin/$GIT_BRANCH
}
|
|
Translate the OS version values into common nomenclature Sets DISTRO from the os_* values |
function GetDistro() {
GetOSVersion
if [[ "$os_VENDOR" =~ (Ubuntu) ]]; then
|
|
'Everyone' refers to Ubuntu releases by the code name adjective |
DISTRO=$os_CODENAME
elif [[ "$os_VENDOR" =~ (Fedora) ]]; then
|
|
For Fedora, just use 'f' and the release |
DISTRO="f$os_RELEASE"
elif [[ "$os_VENDOR" =~ (openSUSE) ]]; then
DISTRO="opensuse-$os_RELEASE"
elif [[ "$os_VENDOR" =~ (SUSE LINUX) ]]; then
|
|
For SLE, also use the service pack |
if [[ -z "$os_UPDATE" ]]; then
DISTRO="sle${os_RELEASE}"
else
DISTRO="sle${os_RELEASE}sp${os_UPDATE}"
fi
else
|
|
Catch-all for now is Vendor + Release + Update |
DISTRO="$os_VENDOR-$os_RELEASE.$os_UPDATE"
fi
export DISTRO
}
|
|
Determine if current distribution is an Ubuntu-based distribution. It will also detect non-Ubuntu but Debian-based distros; this is not an issue since Debian and Ubuntu should be compatible. is_ubuntu |
function is_ubuntu {
if [[ -z "$os_PACKAGE" ]]; then
GetOSVersion
fi
[ "$os_PACKAGE" = "deb" ]
}
|
|
Determine if current distribution is a Fedora-based distribution (Fedora, RHEL, CentOS). is_fedora |
function is_fedora {
if [[ -z "$os_VENDOR" ]]; then
GetOSVersion
fi
[ "$os_VENDOR" = "Fedora" ] || [ "$os_VENDOR" = "Red Hat" ] || [ "$os_VENDOR" = "CentOS" ]
}
|
|
Determine if current distribution is a SUSE-based distribution (openSUSE, SLE). is_suse |
function is_suse {
if [[ -z "$os_VENDOR" ]]; then
GetOSVersion
fi
[ "$os_VENDOR" = "openSUSE" ] || [ "$os_VENDOR" = "SUSE LINUX" ]
}
|
|
Exit after outputting a message about the distribution not being supported. exit_distro_not_supported [optional-string-telling-what-is-missing] |
function exit_distro_not_supported {
if [[ -z "$DISTRO" ]]; then
GetDistro
fi
if [ $# -gt 0 ]; then
echo "Support for $DISTRO is incomplete: no support for $@"
else
echo "Support for $DISTRO is incomplete."
fi
exit 1
}
|
|
git clone only if directory doesn't exist already. Since DEST might not be owned by the installation user, we create the directory and change the ownership to the proper user. Set global RECLONE=yes to simulate a clone when dest-dir exists Set global ERROR_ON_CLONE=True to abort execution with an error if the git repo does not exist (default is False, meaning the repo will be cloned). Uses global OFFLINE git_clone remote dest-dir branch |
function git_clone {
[[ "$OFFLINE" = "True" ]] && return
GIT_REMOTE=$1
GIT_DEST=$2
GIT_REF=$3
if echo $GIT_REF | egrep -q "^refs"; then
|
|
If our branch name is a gerrit style refs/changes/... |
if [[ ! -d $GIT_DEST ]]; then
[[ "$ERROR_ON_CLONE" = "True" ]] && exit 1
git clone $GIT_REMOTE $GIT_DEST
fi
cd $GIT_DEST
git fetch $GIT_REMOTE $GIT_REF && git checkout FETCH_HEAD
else
|
|
do a full clone only if the directory doesn't exist |
if [[ ! -d $GIT_DEST ]]; then
[[ "$ERROR_ON_CLONE" = "True" ]] && exit 1
git clone $GIT_REMOTE $GIT_DEST
cd $GIT_DEST
|
|
This checkout syntax works for both branches and tags |
git checkout $GIT_REF
elif [[ "$RECLONE" == "yes" ]]; then
|
|
if it does exist then simulate what clone does if asked to RECLONE |
cd $GIT_DEST
|
|
set the url to pull from and fetch |
git remote set-url origin $GIT_REMOTE
git fetch origin
|
|
remove the existing ignored files (like pyc) as they cause breakage (due to the py files having older timestamps than our pyc, so python thinks the pyc files are correct using them) |
find $GIT_DEST -name '*.pyc' -delete
|
|
handle GIT_REF accordingly to type (tag, branch) |
if [[ -n "`git show-ref refs/tags/$GIT_REF`" ]]; then
git_update_tag $GIT_REF
elif [[ -n "`git show-ref refs/heads/$GIT_REF`" ]]; then
git_update_branch $GIT_REF
elif [[ -n "`git show-ref refs/remotes/origin/$GIT_REF`" ]]; then
git_update_remote_branch $GIT_REF
else
echo $GIT_REF is neither branch nor tag
exit 1
fi
fi
fi
}
|
|
Comment an option in an INI file inicomment config-file section option |
function inicomment() {
local file=$1
local section=$2
local option=$3
sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
}
|
|
Uncomment an option in an INI file iniuncomment config-file section option |
function iniuncomment() {
local file=$1
local section=$2
local option=$3
sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
}
|
|
Get an option from an INI file iniget config-file section option |
function iniget() {
local file=$1
local section=$2
local option=$3
local line
line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
echo ${line#*=}
}
|
|
Determinate is the given option present in the INI file ini_has_option config-file section option |
function ini_has_option() {
local file=$1
local section=$2
local option=$3
local line
line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
[ -n "$line" ]
}
|
|
Set an option in an INI file iniset config-file section option value |
function iniset() {
local file=$1
local section=$2
local option=$3
local value=$4
if ! grep -q "^\[$section\]" "$file"; then
|
|
Add section at the end |
echo -e "\n[$section]" >>"$file"
fi
if ! ini_has_option "$file" "$section" "$option"; then
|
|
Add it |
sed -i -e "/^\[$section\]/ a\\
$option = $value
" "$file"
else
|
|
Replace it |
sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file"
fi
}
|
|
is_service_enabled() checks if the service(s) specified as arguments are enabled by the user in ENABLED_SERVICES. Multiple services specified as arguments are OR'ed together; the test is a short-circuit boolean, i.e it returns on the first match.
Uses global ENABLED_SERVICES is_service_enabled service [service ...] |
function is_service_enabled() {
services=$@
for service in ${services}; do
[[ ,${ENABLED_SERVICES}, =~ ,${service}, ]] && return 0
[[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && return 0
[[ ${service} == "cinder" && ${ENABLED_SERVICES} =~ "c-" ]] && return 0
[[ ${service} == "ceilometer" && ${ENABLED_SERVICES} =~ "ceilometer-" ]] && return 0
[[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && return 0
[[ ${service} == "quantum" && ${ENABLED_SERVICES} =~ "q-" ]] && return 0
done
return 1
}
|
|
remove extra commas from the input string (i.e. ENABLED_SERVICES) _cleanup_service_list service-list |
function _cleanup_service_list () {
echo "$1" | sed -e '
s/,,/,/g;
s/^,//;
s/,$//
'
}
|
|
enable_service() adds the services passed as argument to the ENABLED_SERVICES list, if they are not already present.
This function does not know about the special cases for nova, glance, and quantum built into is_service_enabled(). Uses global ENABLED_SERVICES enable_service service [service ...] |
function enable_service() {
local tmpsvcs="${ENABLED_SERVICES}"
for service in $@; do
if ! is_service_enabled $service; then
tmpsvcs+=",$service"
fi
done
ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
disable_negated_services
}
|
|
disable_service() removes the services passed as argument to the ENABLED_SERVICES list, if they are present.
This function does not know about the special cases for nova, glance, and quantum built into is_service_enabled(). Uses global ENABLED_SERVICES disable_service service [service ...] |
function disable_service() {
local tmpsvcs=",${ENABLED_SERVICES},"
local service
for service in $@; do
if is_service_enabled $service; then
tmpsvcs=${tmpsvcs//,$service,/,}
fi
done
ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
}
|
|
disable_all_services() removes all current services from ENABLED_SERVICES to reset the configuration before a minimal installation Uses global ENABLED_SERVICES disable_all_services |
function disable_all_services() {
ENABLED_SERVICES=""
}
|
|
Remove all services starting with '-'. For example, to install all default services except rabbit (rabbit) set in localrc: ENABLED_SERVICES+=",-rabbit" Uses global ENABLED_SERVICES disable_negated_services |
function disable_negated_services() {
local tmpsvcs="${ENABLED_SERVICES}"
local service
for service in ${tmpsvcs//,/ }; do
if [[ ${service} == -* ]]; then
tmpsvcs=$(echo ${tmpsvcs}|sed -r "s/(,)?(-)?${service#-}(,)?/,/g")
fi
done
ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
}
|
|
Distro-agnostic package installer install_package package [package ...] |
function install_package() {
if is_ubuntu; then
[[ "$NO_UPDATE_REPOS" = "True" ]] || apt_get update
NO_UPDATE_REPOS=True
apt_get install "$@"
elif is_fedora; then
yum_install "$@"
elif is_suse; then
zypper_install "$@"
else
exit_distro_not_supported "installing packages"
fi
}
|
|
Distro-agnostic function to tell if a package is installed is_package_installed package [package ...] |
function is_package_installed() {
if [[ -z "$@" ]]; then
return 1
fi
if [[ -z "$os_PACKAGE" ]]; then
GetOSVersion
fi
if [[ "$os_PACKAGE" = "deb" ]]; then
dpkg -l "$@" > /dev/null
elif [[ "$os_PACKAGE" = "rpm" ]]; then
rpm --quiet -q "$@"
else
exit_distro_not_supported "finding if a package is installed"
fi
}
|
|
Test if the named environment variable is set and not zero length is_set env-var |
function is_set() {
local var=\$"$1"
eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
}
|
|
Wrapper for pip install to set cache and proxy environment variables Uses globals OFFLINE, PIP_DOWNLOAD_CACHE, PIP_USE_MIRRORS, pip_install package [package ...] |
function pip_install {
[[ "$OFFLINE" = "True" || -z "$@" ]] && return
if [[ -z "$os_PACKAGE" ]]; then
GetOSVersion
fi
if [[ $TRACK_DEPENDS = True ]] ; then
source $DEST/.venv/bin/activate
CMD_PIP=$DEST/.venv/bin/pip
SUDO_PIP="env"
else
SUDO_PIP="sudo"
CMD_PIP=$(get_pip_command)
fi
if [[ "$PIP_USE_MIRRORS" != "False" ]]; then
PIP_MIRROR_OPT="--use-mirrors"
fi
$SUDO_PIP PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \
HTTP_PROXY=$http_proxy \
HTTPS_PROXY=$https_proxy \
NO_PROXY=$no_proxy \
$CMD_PIP install $PIP_MIRROR_OPT $@
}
|
|
Service wrapper to restart services restart_service service-name |
function restart_service() {
if is_ubuntu; then
sudo /usr/sbin/service $1 restart
else
sudo /sbin/service $1 restart
fi
}
|
|
Helper to launch a service in a named screen screen_it service "command-line" |
function screen_it {
SCREEN_NAME=${SCREEN_NAME:-stack}
SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
SCREEN_DEV=`trueorfalse True $SCREEN_DEV`
if is_service_enabled $1; then
|
|
Append the service to the screen rc file |
screen_rc "$1" "$2"
screen -S $SCREEN_NAME -X screen -t $1
if [[ -n ${SCREEN_LOGDIR} ]]; then
screen -S $SCREEN_NAME -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
screen -S $SCREEN_NAME -p $1 -X log on
ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
fi
if [[ "$SCREEN_DEV" = "True" ]]; then
|
|
sleep to allow bash to be ready to be send the command - we are creating a new window in screen and then sends characters, so if bash isn't running by the time we send the command, nothing happens |
sleep 1.5
NL=`echo -ne '\015'`
screen -S $SCREEN_NAME -p $1 -X stuff "$2 || touch \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL"
else
screen -S $SCREEN_NAME -p $1 -X exec /bin/bash -c "$2 || touch \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\""
fi
fi
}
|
|
Screen rc file builder screen_rc service "command-line" |
function screen_rc {
SCREEN_NAME=${SCREEN_NAME:-stack}
SCREENRC=$TOP_DIR/$SCREEN_NAME-screenrc
if [[ ! -e $SCREENRC ]]; then
|
|
Name the screen session |
echo "sessionname $SCREEN_NAME" > $SCREENRC
|
|
Set a reasonable statusbar |
echo "hardstatus alwayslastline '$SCREEN_HARDSTATUS'" >> $SCREENRC
echo "screen -t shell bash" >> $SCREENRC
fi
|
|
If this service doesn't already exist in the screenrc file |
if ! grep $1 $SCREENRC 2>&1 > /dev/null; then
NL=`echo -ne '\015'`
echo "screen -t $1 bash" >> $SCREENRC
echo "stuff \"$2$NL\"" >> $SCREENRC
fi
}
|
|
Helper to remove the *.failure files under $SERVICE_DIR/$SCREEN_NAME This is used for service_check when all the screen_it are called finished init_service_check |
function init_service_check() {
SCREEN_NAME=${SCREEN_NAME:-stack}
SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
if [[ ! -d "$SERVICE_DIR/$SCREEN_NAME" ]]; then
mkdir -p "$SERVICE_DIR/$SCREEN_NAME"
fi
rm -f "$SERVICE_DIR/$SCREEN_NAME"/*.failure
}
|
|
Helper to get the status of each running service service_check |
function service_check() {
local service
local failures
SCREEN_NAME=${SCREEN_NAME:-stack}
SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
if [[ ! -d "$SERVICE_DIR/$SCREEN_NAME" ]]; then
echo "No service status directory found"
return
fi
|
|
Check if there is any falure flag file under $SERVICE_DIR/$SCREEN_NAME |
failures=`ls "$SERVICE_DIR/$SCREEN_NAME"/*.failure 2>/dev/null`
for service in $failures; do
service=`basename $service`
service=${service::-8}
echo "Error: Service $service is not running"
done
if [ -n "$failures" ]; then
echo "More details about the above errors can be found with screen, with ./rejoin-stack.sh"
fi
}
|
|
pip install the dependencies of the package before setup.py develop so pip and not distutils processes the dependency chain Uses globals TRACK_DEPENDES, ``*_proxy` setup_develop directory |
function setup_develop() {
if [[ $TRACK_DEPENDS = True ]] ; then
SUDO_CMD="env"
else
SUDO_CMD="sudo"
fi
(cd $1; \
python setup.py egg_info; \
raw_links=$(awk '/^.+/ {print "-f " $1}' *.egg-info/dependency_links.txt); \
depend_links=$(echo $raw_links | xargs); \
require_file=$([ ! -r *-info/requires.txt ] || echo "-r *-info/requires.txt"); \
pip_install $require_file $depend_links; \
$SUDO_CMD \
HTTP_PROXY=$http_proxy \
HTTPS_PROXY=$https_proxy \
NO_PROXY=$no_proxy \
python setup.py develop \
)
}
|
|
Service wrapper to start services start_service service-name |
function start_service() {
if is_ubuntu; then
sudo /usr/sbin/service $1 start
else
sudo /sbin/service $1 start
fi
}
|
|
Service wrapper to stop services stop_service service-name |
function stop_service() {
if is_ubuntu; then
sudo /usr/sbin/service $1 stop
else
sudo /sbin/service $1 stop
fi
}
|
|
Normalize config values to True or False Accepts as False: 0 no false False FALSE Accepts as True: 1 yes true True TRUE VAR=$(trueorfalse default-value test-value) |
function trueorfalse() {
local default=$1
local testval=$2
[[ -z "$testval" ]] && { echo "$default"; return; }
[[ "0 no false False FALSE" =~ "$testval" ]] && { echo "False"; return; }
[[ "1 yes true True TRUE" =~ "$testval" ]] && { echo "True"; return; }
echo "$default"
}
|
|
Retrieve an image from a URL and upload into Glance Uses the following variables: FILES must be set to the cache dir GLANCE_HOSTPORT upload_image image-url glance-token |
function upload_image() {
local image_url=$1
local token=$2
|
|
Create a directory for the downloaded image tarballs. |
mkdir -p $FILES/images
|
|
Downloads the image (uec ami+aki style), then extracts it. |
IMAGE_FNAME=`basename "$image_url"`
if [[ ! -f $FILES/$IMAGE_FNAME || "$(stat -c "%s" $FILES/$IMAGE_FNAME)" = "0" ]]; then
wget -c $image_url -O $FILES/$IMAGE_FNAME
if [[ $? -ne 0 ]]; then
echo "Not found: $image_url"
return
fi
fi
|
|
OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading |
if [[ "$image_url" =~ 'openvz' ]]; then
IMAGE="$FILES/${IMAGE_FNAME}"
IMAGE_NAME="${IMAGE_FNAME%.tar.gz}"
glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public=True --container-format ami --disk-format ami < "${IMAGE}"
return
fi
KERNEL=""
RAMDISK=""
DISK_FORMAT=""
CONTAINER_FORMAT=""
UNPACK=""
case "$IMAGE_FNAME" in
*.tar.gz|*.tgz)
|
|
Extract ami and aki files |
[ "${IMAGE_FNAME%.tar.gz}" != "$IMAGE_FNAME" ] &&
IMAGE_NAME="${IMAGE_FNAME%.tar.gz}" ||
IMAGE_NAME="${IMAGE_FNAME%.tgz}"
xdir="$FILES/images/$IMAGE_NAME"
rm -Rf "$xdir";
mkdir "$xdir"
tar -zxf $FILES/$IMAGE_FNAME -C "$xdir"
KERNEL=$(for f in "$xdir/"*-vmlinuz* "$xdir/"aki-*/image; do
[ -f "$f" ] && echo "$f" && break; done; true)
RAMDISK=$(for f in "$xdir/"*-initrd* "$xdir/"ari-*/image; do
[ -f "$f" ] && echo "$f" && break; done; true)
IMAGE=$(for f in "$xdir/"*.img "$xdir/"ami-*/image; do
[ -f "$f" ] && echo "$f" && break; done; true)
if [[ -z "$IMAGE_NAME" ]]; then
IMAGE_NAME=$(basename "$IMAGE" ".img")
fi
;;
*.img)
IMAGE="$FILES/$IMAGE_FNAME";
IMAGE_NAME=$(basename "$IMAGE" ".img")
format=$(qemu-img info ${IMAGE} | awk '/^file format/ { print $3; exit }')
if [[ ",qcow2,raw,vdi,vmdk,vpc," =~ ",$format," ]]; then
DISK_FORMAT=$format
else
DISK_FORMAT=raw
fi
CONTAINER_FORMAT=bare
;;
*.img.gz)
IMAGE="$FILES/${IMAGE_FNAME}"
IMAGE_NAME=$(basename "$IMAGE" ".img.gz")
DISK_FORMAT=raw
CONTAINER_FORMAT=bare
UNPACK=zcat
;;
*.qcow2)
IMAGE="$FILES/${IMAGE_FNAME}"
IMAGE_NAME=$(basename "$IMAGE" ".qcow2")
DISK_FORMAT=qcow2
CONTAINER_FORMAT=bare
;;
*) echo "Do not know what to do with $IMAGE_FNAME"; false;;
esac
if [ "$CONTAINER_FORMAT" = "bare" ]; then
if [ "$UNPACK" = "zcat" ]; then
glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --public --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < <(zcat --force "${IMAGE}")
else
glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --public --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < "${IMAGE}"
fi
else
|
|
Use glance client to add the kernel the root filesystem. We parse the results of the first upload to get the glance ID of the kernel for use when uploading the root filesystem. |
KERNEL_ID=""; RAMDISK_ID="";
if [ -n "$KERNEL" ]; then
KERNEL_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-kernel" --public --container-format aki --disk-format aki < "$KERNEL" | grep ' id ' | get_field 2)
fi
if [ -n "$RAMDISK" ]; then
RAMDISK_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-ramdisk" --public --container-format ari --disk-format ari < "$RAMDISK" | grep ' id ' | get_field 2)
fi
glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "${IMAGE_NAME%.img}" --public --container-format ami --disk-format ami ${KERNEL_ID:+--property kernel_id=$KERNEL_ID} ${RAMDISK_ID:+--property ramdisk_id=$RAMDISK_ID} < "${IMAGE}"
fi
}
|
|
Set the database backend to use When called from stackrc/localrc DATABASE_BACKENDS has not been initialized yet, just save the configuration selection and call back later to validate it. $1 The name of the database backend to use (mysql, postgresql, ...) |
function use_database {
if [[ -z "$DATABASE_BACKENDS" ]]; then
|
|
The backends haven't initialized yet, just save the selection for now |
DATABASE_TYPE=$1
else
use_exclusive_service DATABASE_BACKENDS DATABASE_TYPE $1
fi
}
|
|
function use_exclusive_service {
local options=${!1}
local selection=$3
out=$2
[ -z $selection ] || [[ ! "$options" =~ "$selection" ]] && return 1
for opt in $options;do
[[ "$opt" = "$selection" ]] && enable_service $opt || disable_service $opt
done
eval "$out=$selection"
return 0
}
|
|
Wait for an HTTP server to start answering requests wait_for_service timeout url |
function wait_for_service() {
local timeout=$1
local url=$2
timeout $timeout sh -c "while ! http_proxy= https_proxy= curl -s $url >/dev/null; do sleep 1; done"
}
|
|
Wrapper for yum to set proxy environment variables Uses globals OFFLINE, ``*_proxy` yum_install package [package ...] |
function yum_install() {
[[ "$OFFLINE" = "True" ]] && return
local sudo="sudo"
[[ "$(id -u)" = "0" ]] && sudo="env"
$sudo http_proxy=$http_proxy https_proxy=$https_proxy \
no_proxy=$no_proxy \
yum install -y "$@"
}
|
|
ping check Uses globals ENABLED_SERVICES |
function ping_check() {
if is_service_enabled quantum; then
_ping_check_quantum "$1" $2 $3 $4
return
fi
_ping_check_novanet "$1" $2 $3 $4
}
|
|
ping check for nova Uses globals MULTI_HOST, PRIVATE_NETWORK |
function _ping_check_novanet() {
local from_net=$1
local ip=$2
local boot_timeout=$3
local expected=${4:-"True"}
local check_command=""
MULTI_HOST=`trueorfalse False $MULTI_HOST`
if [[ "$MULTI_HOST" = "True" && "$from_net" = "$PRIVATE_NETWORK_NAME" ]]; then
sleep $boot_timeout
return
fi
if [[ "$expected" = "True" ]]; then
check_command="while ! ping -c1 -w1 $ip; do sleep 1; done"
else
check_command="while ping -c1 -w1 $ip; do sleep 1; done"
fi
if ! timeout $boot_timeout sh -c "$check_command"; then
if [[ "$expected" = "True" ]]; then
echo "[Fail] Couldn't ping server"
else
echo "[Fail] Could ping server"
fi
exit 1
fi
}
|
|
ssh check |
function ssh_check() {
if is_service_enabled quantum; then
_ssh_check_quantum "$1" $2 $3 $4 $5
return
fi
_ssh_check_novanet "$1" $2 $3 $4 $5
}
function _ssh_check_novanet() {
local NET_NAME=$1
local KEY_FILE=$2
local FLOATING_IP=$3
local DEFAULT_INSTANCE_USER=$4
local ACTIVE_TIMEOUT=$5
local probe_cmd=""
if ! timeout $ACTIVE_TIMEOUT sh -c "while ! ssh -o StrictHostKeyChecking=no -i $KEY_FILE ${DEFAULT_INSTANCE_USER}@$FLOATING_IP echo success ; do sleep 1; done"; then
echo "server didn't become ssh-able!"
exit 1
fi
}
|
|
zypper wrapper to set arguments correctly zypper_install package [package ...] |
function zypper_install() {
[[ "$OFFLINE" = "True" ]] && return
local sudo="sudo"
[[ "$(id -u)" = "0" ]] && sudo="env"
$sudo http_proxy=$http_proxy https_proxy=$https_proxy \
zypper --non-interactive install --auto-agree-with-licenses "$@"
}
|
|
Add a user to a group. add_user_to_group user group |
function add_user_to_group() {
local user=$1
local group=$2
if [[ -z "$os_VENDOR" ]]; then
GetOSVersion
fi
|
|
SLE11 and openSUSE 12.2 don't have the usual usermod |
if ! is_suse || [[ "$os_VENDOR" = "openSUSE" && "$os_RELEASE" != "12.2" ]]; then
sudo usermod -a -G "$group" "$user"
else
sudo usermod -A "$group" "$user"
fi
}
|
|
Get the path to the direcotry where python executables are installed. get_python_exec_prefix |
function get_python_exec_prefix() {
if is_fedora; then
echo "/usr/bin"
else
echo "/usr/local/bin"
fi
}
|
|
Get the location of the $module-rootwrap executables, where module is cinder or nova. get_rootwrap_location module |
function get_rootwrap_location() {
local module=$1
echo "$(get_python_exec_prefix)/$module-rootwrap"
}
|
|
Get the path to the pip command. get_pip_command |
function get_pip_command() {
if is_fedora; then
which pip-python
else
which pip
fi
}
|
|
Restore xtrace |
$XTRACE
|
|
Local variables: -- mode: Shell-script -- End: |
|
| |