Files
training-labs/labs/osbash/lib/functions.guest.sh
Roger Luethi c5fdafc900 Newton updates
This changeset contains updates for Newton.

Notable changes include:
- Ubuntu 14.04 LTS (trusty) replaced by Ubuntu 16.04 LTS (xenial)
- Higher RAM requirements, the controller VM needs 5120 MB
- Script order changed (install-guide changes)
- By default, mariadb does not use a root password but socket auth (sudo)
- Nova does not configure any default flavors anymore; we create m1.nano
  and that's all there is when the cluster is built.
- Remaining differences to install-guide marked in the source code
- As always, new races fixed

Change-Id: Id59e145140252c4384584a3899e01a38e8a57158
2016-10-17 13:40:06 +02:00

459 lines
14 KiB
Bash

# This file contains bash functions that may be used by guest systems (VMs).
# Sourcing this file calls functions fix_path_env and source_deploy.
source "$LIB_DIR/functions.sh"
source "$LIB_DIR/functions-common-devstack"
# Make devstack's operating system identification work with nounset
function init_os_ident {
if [[ -z "${os_PACKAGE:-""}" ]]; then
GetOSVersion
fi
}
function source_deploy {
if [ -n "${VM_SHELL_USER:-}" ]; then
# Already sourced
return 0
fi
if mountpoint -q /vagrant; then
source "$CONFIG_DIR/deploy.vagrant"
else
source "$CONFIG_DIR/deploy.osbash"
fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# If our sudo user's PATH is preserved (and does not contain sbin dirs),
# some commands won't be found. Observed with Vagrant shell provisioner
# scripts using sudo after "su - vagrant".
# Adding to the path seems preferable to messing with the vagrant user's
# sudoers environment (or working with a separate Vagrant user).
function fix_path_env {
if is_root; then return 0; fi
if echo 'echo $PATH'|sudo sh|grep -q '/sbin'; then return 0; fi
export PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function zero_empty_space {
echo "Filling empty disk space with zeros"
sudo dd if=/dev/zero of=/filler bs=1M 2>/dev/null || true
sudo rm /filler
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# For guest scripts to let osbash know they are running; used when osbashauto
# runs scripts inside of the VM (STATUS_DIR directory must be shared between
# host and VM).
function indicate_current_auto {
if [ "${VM_SHELL_USER:-}" = "osbash" ]; then
local scr_name=${1:-$(basename "$0")}
local fpath=${2:-"/$STATUS_DIR/$scr_name.begin"}
mkdir -p "$STATUS_DIR"
touch "$fpath"
fi
log_point "script begin"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Debug function to make a script halt execution until a tmp file is removed
function wait_for_file {
# If no argument is passed, use empty string (to pass nounset option)
local msg=${1-""}
local wait_file=remove_to_continue
[ -n "$msg" ] && wait_file=${wait_file}_${msg}
echo >&2 "DEBUG wait_for_file pause; remove /tmp/$wait_file to continue."
touch "/tmp/$wait_file"
while [ -e "/tmp/$wait_file" ]; do
sleep 1
done
}
#-------------------------------------------------------------------------------
# Copy stdin/stderr to log file
#-------------------------------------------------------------------------------
function exec_logpath {
local log_path=$1
# Append all stdin and stderr to log file
exec > >(tee -a "$log_path") 2>&1
}
function exec_logfile {
local log_dir=${1:-/home/$VM_SHELL_USER/log}
# Default extension is log
local ext=${2:-log}
mkdir -p "$log_dir"
# Log name based on name of running script
local base_name=$(basename "$0" .sh)
local prefix=$(get_next_prefix "$log_dir" "$ext")
local log_name="${prefix}_$base_name.$ext"
exec_logpath "$log_dir/$log_name"
}
#-------------------------------------------------------------------------------
# Functions that need to run as root
#-------------------------------------------------------------------------------
function as_root_fix_mount_vboxsf_link {
local file=/sbin/mount.vboxsf
if [ -L $file -a ! -e $file ]; then
echo "$file is a broken symlink. Trying to fix it."
shopt -s nullglob
local new=(/opt/VBoxGuestAdditions*/lib/VBoxGuestAdditions)
if [ -n "$new" ]; then
ln -sv "$new" /usr/lib/VBoxGuestAdditions
else
return 1
fi
fi
}
function as_root_inject_sudoer {
if grep -q "${VM_SHELL_USER}" /etc/sudoers; then
echo "${VM_SHELL_USER} already in /etc/sudoers"
else
echo "${VM_SHELL_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "Defaults:${VM_SHELL_USER} !requiretty" >> /etc/sudoers
fi
}
# Change to a regular user to execute a guest script (and log its output)
function as_root_exec_script {
local script_path=$1
local script_name="$(basename "$script_path" .sh)"
echo "$(date) start $script_path"
local prefix=$(get_next_prefix "$LOG_DIR" "auto")
local log_path=$LOG_DIR/${prefix}_$script_name.auto
su - "$VM_SHELL_USER" -c "bash $script_path" >"$log_path" 2>&1
local rc=$?
if [ $rc -ne 0 ]; then
echo "$(date) ERROR: status $rc for $script_path" |
tee >&2 -a "$LOG_DIR/error.log"
else
echo "$(date) done"
fi
return $rc
}
#-------------------------------------------------------------------------------
# Root wrapper around devstack functions for manipulating config files
#-------------------------------------------------------------------------------
# Return predictable temporary path for configuration file editing.
# Used to simplify debugging.
function get_iniset_tmpfile {
local file=$1
# Set tmpdir="$LOG_DIR" if you want the temporary files to survive reboots.
local tmpdir="/tmp"
local ext="iniset"
local prefix=$(get_next_prefix "$tmpdir" "$ext")
# Typical tmpfile path: /tmp/000_etc_keystone_keystone.conf.iniset
local tmpfile=$tmpdir/$prefix$(echo "$file" | tr '/' '_').$ext
# Create file owned by regular user so it can be edited without privileges
touch "$tmpfile"
echo "$tmpfile"
}
# Set an option in an INI file
# iniset config-file section option value
function iniset_sudo {
if (($# != 4)); then
echo -n "ERROR: $# instead of 4 arguments for iniset: $*"
exit 1
fi
local file=$1
shift
local tmpfile=$(get_iniset_tmpfile "$file")
# Create a temporary copy, work on it, and copy it back into place
sudo cp -fv "$file" "$tmpfile"
echo >&2 iniset "$tmpfile" "$@"
iniset "$tmpfile" "$@"
cat "$tmpfile" | sudo tee "$file" >/dev/null
}
# Comment an option in an INI file
# inicomment config-file section option
function inicomment_sudo {
local file=$1
shift
local tmpfile=$(get_iniset_tmpfile "$file")
# Create a temporary copy, work on it, and copy it back into place
sudo cp -fv "$file" "$tmpfile"
echo >&2 inicomment "$tmpfile" "$@"
inicomment "$tmpfile" "$@"
cat "$tmpfile" | sudo tee "$file" >/dev/null
}
# Determinate is the given option present in the INI file
# ini_has_option config-file section option
function ini_has_option_sudo {
local file=$1
shift
local tmpfile=$(get_iniset_tmpfile "$file")
# Create a temporary copy, work on it
sudo cp -fv "$file" "$tmpfile"
echo >&2 ini_has_option "$tmpfile" "$@"
ini_has_option "$tmpfile" "$@"
}
#-------------------------------------------------------------------------------
# Functions for manipulating config files without section
#-------------------------------------------------------------------------------
function iniset_sudo_no_section {
local file=$1
shift
local tmpfile=$(get_iniset_tmpfile "$file")
# Create a temporary copy, work on it, and copy it back into place
sudo cp -fv "$file" "$tmpfile"
iniset_no_section "$tmpfile" "$@"
cat "$tmpfile" | sudo tee "$file" >/dev/null
}
# ini_has_option_no_section config-file option
function ini_has_option_no_section {
local xtrace=$(set +o | grep xtrace)
set +o xtrace
local file=$1
local option=$2
local line
line=$(sed -ne "/^$option[ \t]*=/ p;" "$file")
$xtrace
[ -n "$line" ]
}
# Set an option in an INI file
# iniset_no_section config-file option value
function iniset_no_section {
local xtrace=$(set +o | grep xtrace)
set +o xtrace
local file=$1
local option=$2
local value=$3
[[ -z $option ]] && return
if ! ini_has_option_no_section "$file" "$option"; then
# Add it
sed -i -e "1 i\
$option = $value
" "$file"
else
local sep=$(echo -ne "\x01")
# Replace it
sed -i -e '/^'${option}'/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
fi
$xtrace
}
#-------------------------------------------------------------------------------
# OpenStack helpers
#-------------------------------------------------------------------------------
function mysql_exe {
local cmd="$1"
echo "mysql cmd: $cmd."
# XXX install-guide uses password, but distro install uses socket auth
sudo mysql -u "root" -e "$cmd"
}
function setup_database {
local service=$1
local db_user=$2
local db_password=$3
echo -n "Waiting for database server to come up."
until mysql_exe quit >/dev/null 2>&1; do
sleep 1
echo -n .
done
echo
mysql_exe "CREATE DATABASE $service"
mysql_exe "GRANT ALL ON ${service}.* TO '$db_user'@'%' IDENTIFIED BY '$db_password';"
mysql_exe "GRANT ALL ON ${service}.* TO '$db_user'@'localhost' IDENTIFIED BY '$db_password';"
}
# Wait for neutron to come up. Due to a race during the operating system boot
# process, the neutron server sometimes fails to come up. We restart the
# neutron server if it does not reply for too long.
function wait_for_neutron {
(
source $CONFIG_DIR/demo-openstackrc.sh
echo -n "Waiting for neutron to come up."
local cnt=0
until openstack network list >/dev/null 2>&1; do
if [ "$cnt" -eq 10 ]; then
echo
echo "ERROR No response from neutron. Restarting neutron-server."
node_ssh controller "sudo service neutron-server restart"
echo -n "Waiting for neutron to come up."
elif [ "$cnt" -eq 20 ]; then
echo
echo "ERROR neutron does not seem to come up. Aborting."
exit 1
fi
echo -n .
sleep 1
cnt=$((cnt + 1))
done
echo
)
}
# Wait for keystone to come up
function wait_for_keystone {
(
source "$CONFIG_DIR/admin-openstackrc.sh"
echo -n "Waiting for keystone to come up."
until openstack user list >/dev/null 2>&1; do
echo -n .
sleep 1
done
echo
)
}
#-------------------------------------------------------------------------------
# Network configuration
#-------------------------------------------------------------------------------
# Return the nth network interface name (not counting loopback; 0 -> eth0)
function ifnum_to_ifname {
local if_num=$1
# Skip loopback and start counting with next interface
local iface=${IF_NAMES[$((if_num + 1))]}
echo >&2 "ifnum_to_ifname: interface $if_num is $iface"
echo "$iface"
}
# Get all network interfaces (e.g. eth0, p2p1, ens0, enp0s3) into an array
function set_iface_list {
unset IF_NAMES
local iface
for iface in $(ip -o link show|awk '/: / {print $2}'|tr -d ':'); do
IF_NAMES+=($iface)
done
echo "Set IF_NAMES to ${IF_NAMES[*]}"
}
# Return the nth network interface name (not counting loopback; 0 -> eth0)
function ifnum_to_ifname {
local if_num=$1
# Skip loopback and start counting with next interface
local iface=${IF_NAMES[$((if_num + 1))]}
echo >&2 "ifnum_to_ifname: interface $if_num is $iface"
echo "$iface"
}
# Get all network interfaces (e.g. eth0, p2p1, ens0, enp0s3) into an array
function set_iface_list {
unset IF_NAMES
local iface
for iface in $(ip -o link show|awk '/: / {print $2}'|tr -d ':'); do
IF_NAMES+=($iface)
done
echo "Set IF_NAMES to ${IF_NAMES[*]}"
}
function hostname_to_ip {
local host_name=$1
getent hosts "$host_name"|awk '{print $1}'
}
function config_network {
init_os_ident
if is_ubuntu; then
source "$LIB_DIR/functions.ubuntu.sh"
else
source "$LIB_DIR/functions.fedora.sh"
fi
netcfg_init
# Get network interface configuration (NET_IF_?) for this node
unset -v NET_IF_0 NET_IF_1 NET_IF_2 NET_IF_3
get_node_netif_config "$(hostname)"
local index
local iftype
for index in "${!NODE_IF_TYPE[@]}"; do
iftype=${NODE_IF_TYPE[index]}
config_netif "$iftype" "$index" "${NODE_IF_IP[index]}"
done
}
#-------------------------------------------------------------------------------
# Log points
#------------------------------------------------------------------------------
# Record current size of log files of interest so we can later split them
# accordingly.
# Log points can be set anywhere in a client script simply by adding a
# line: log_point "log point name"
function log_point {
local caller=$(basename "$0" .sh)
local commit_msg=$1
local logdir=${2:-/var/log}
local ext=lsl
local prefix=$(get_next_prefix "$logdir" "$ext")
local fname
fname=${prefix}_$(echo "${caller}_-_$commit_msg"|tr ' ' '_').$ext
(
cd "$logdir"
sudo bash -c "shopt -s nullglob; ls -l auth.log* keystone/* upstart/*.log mysql/* neutron/*" | \
sudo tee "$logdir/$fname" > /dev/null
)
}
#-------------------------------------------------------------------------------
# ssh wrapper functions
#-------------------------------------------------------------------------------
function no_chk_ssh {
echo >&2 "ssh $*"
# Options set to disable strict host key checking and related messages.
ssh \
-o "UserKnownHostsFile /dev/null" \
-o "StrictHostKeyChecking no" \
-o LogLevel=error \
"$@"
}
# ssh from one node VM to another node in the cluster
function node_ssh {
no_chk_ssh -i "$HOME/.ssh/osbash_key" "$@"
}
#-------------------------------------------------------------------------------
fix_path_env
source_deploy
#-------------------------------------------------------------------------------
# vim: set ai ts=4 sw=4 et ft=sh: