288 lines
10 KiB
Bash
Executable File
288 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright 2013 Mirantis, Inc.
|
|
#
|
|
# 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.
|
|
|
|
# This file contains the functions for connecting to Fuel VM, checking if the installation process completed
|
|
# and Fuel became operational, and also enabling outbound network/internet access for this VM through the
|
|
# host system
|
|
|
|
source ./functions/shell.sh
|
|
|
|
ssh_options='-oConnectTimeout=5 -oStrictHostKeyChecking=no -oCheckHostIP=no -oUserKnownHostsFile=/dev/null -oRSAAuthentication=no -oPubkeyAuthentication=no'
|
|
|
|
wait_for_line_in_puppet_bootstrap() {
|
|
ip=$1
|
|
username=$2
|
|
password=$3
|
|
prompt=$4
|
|
goodline=$5
|
|
badline=$6
|
|
|
|
# Log in into the VM, see if Puppet has completed its run
|
|
# Looks a bit ugly, but 'end of expect' has to be in the very beginning of the line
|
|
result=$(
|
|
execute expect << ENDOFEXPECT
|
|
spawn ssh $ssh_options $username@$ip
|
|
expect "connect to host" exit
|
|
expect "*?assword:*"
|
|
send "$password\r"
|
|
expect "$prompt"
|
|
send "egrep --color=none -e '$goodline' -e '$badline' /var/log/puppet/bootstrap_admin_node.log\r"
|
|
expect "$prompt"
|
|
send "logout\r"
|
|
expect "$prompt"
|
|
ENDOFEXPECT
|
|
)
|
|
|
|
echo "$result" | egrep "$badline" >&2 && return 1
|
|
echo "$result" | egrep -q "$goodline" && return 0
|
|
return 1
|
|
}
|
|
|
|
is_product_vm_operational() {
|
|
wait_for_line_in_puppet_bootstrap "$@" "^Fuel.*complete" "^Fuel.*FAILED"
|
|
}
|
|
|
|
wait_for_product_vm_to_download() {
|
|
ip=$1
|
|
username=$2
|
|
password=$3
|
|
prompt=$4
|
|
|
|
echo "Waiting for product VM to download files. Please do NOT abort the script..."
|
|
|
|
# Loop until master node gets successfully installed
|
|
maxdelay=3000
|
|
while ! wait_for_line_in_puppet_bootstrap $ip $username $password "$prompt" "dockerctl build all|^Fuel.*complete" "^Fuel.*FAILED"; do
|
|
sleep 5
|
|
((waited += 5))
|
|
if (( waited >= maxdelay )); then
|
|
echo "Installation timed out! ($maxdelay seconds)" 1>&2
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
wait_for_product_vm_to_install() {
|
|
ip=$1
|
|
username=$2
|
|
password=$3
|
|
prompt=$4
|
|
|
|
echo "Waiting for product VM to install. Please do NOT abort the script..."
|
|
|
|
# Loop until master node gets successfully installed
|
|
maxdelay=3000
|
|
while ! is_product_vm_operational $ip $username $password "$prompt"; do
|
|
sleep 5
|
|
((waited += 5))
|
|
if (( waited >= maxdelay )); then
|
|
echo "Installation timed out! ($maxdelay seconds)" 1>&2
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_internet_connection() {
|
|
line=$1
|
|
OIFS="${IFS}"
|
|
NIFS=$' '
|
|
IFS="${NIFS}"
|
|
for i in $line; do
|
|
if [[ "$i" == *% && "$i" != 100* ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
IFS="${OIFS}"
|
|
return 1
|
|
}
|
|
|
|
enable_outbound_network_for_product_vm() {
|
|
ip=$1
|
|
username=$2
|
|
password=$3
|
|
prompt=$4
|
|
interface_id=$(($5-1)) # Subtract one to get ethX index (0-based) from the VirtualBox index (from 1 to 4)
|
|
gateway_ip=$6
|
|
|
|
# Check for internet access on the host system
|
|
echo -n "Checking for internet connectivity on the host system... "
|
|
check_hosts=`echo google.com wikipedia.com | tr ' ' '\n'`
|
|
case $(execute uname) in
|
|
Linux | Darwin)
|
|
for i in ${check_hosts} ; do
|
|
ping_host=`execute ping -c 2 ${i} | grep %`
|
|
ping_host_result+=$ping_host
|
|
done
|
|
;;
|
|
CYGWIN*)
|
|
if [ ! -z "`execute type ping | grep system32`" ]; then
|
|
for i in ${check_hosts} ; do
|
|
ping_host=`execute ping -n 5 ${i} | grep %`
|
|
ping_host_result+=$ping_host
|
|
done
|
|
elif [ ! -z "`execute type ping | grep bin`" ]; then
|
|
for i in ${check_hosts} ; do
|
|
ping_host=`execute ping ${i} count 5 | grep %`
|
|
ping_host_result+=$ping_host
|
|
done
|
|
else
|
|
print_no_internet_connectivity_banner
|
|
fi
|
|
;;
|
|
*)
|
|
print_no_internet_connectivity_banner
|
|
;;
|
|
esac
|
|
|
|
check_internet_connection "$ping_host_result"
|
|
if [[ $? -eq 0 ]]; then
|
|
echo "OK"
|
|
else
|
|
print_no_internet_connectivity_banner
|
|
fi
|
|
|
|
# Check host nameserver configuration
|
|
echo -n "Checking local DNS configuration... "
|
|
if execute test -f /etc/resolv.conf ; then
|
|
nameserver="$(execute grep '^nameserver' /etc/resolv.conf | grep -v 'nameserver\s\s*127.' | head -3)"
|
|
fi
|
|
if [ -z "$nameserver" ] && execute test -x /usr/bin/nmcli; then
|
|
# Get DNS from network manager
|
|
if [ -n "`execute LANG=C nmcli nm | grep \"running\s\+connected\"`" ]; then
|
|
nameserver="$(execute nmcli dev list | grep 'IP[46].DNS' | sed -e 's/IP[46]\.DNS\[[0-9]\+\]:\s\+/nameserver /'| grep -v 'nameserver\s\s*127.' | head -3)"
|
|
fi
|
|
fi
|
|
if [ -z "$nameserver" ]; then
|
|
echo "/etc/resolv.conf does not contain a nameserver. Using 8.8.8.8 for DNS."
|
|
nameserver="nameserver 8.8.8.8"
|
|
else
|
|
echo "OK"
|
|
fi
|
|
|
|
# Enable internet access on inside the VMs
|
|
echo -n "Enabling outbound network/internet access for the product VM... "
|
|
|
|
# Get network settings (ip address and ip network) for eth1 interface of the master node
|
|
local master_ip_pub_net=$(echo $fuel_master_ips | cut -f2 -d ' ')
|
|
master_ip_pub_net="${master_ip_pub_net%.*}"".1"
|
|
local master_pub_net="${master_ip_pub_net%.*}"".0"
|
|
|
|
# Log in into the VM, configure and bring up the NAT interface, set default gateway, check internet connectivity
|
|
# Looks a bit ugly, but 'end of expect' has to be in the very beginning of the line
|
|
result=$(
|
|
execute expect << ENDOFEXPECT
|
|
spawn ssh $ssh_options $username@$ip
|
|
expect "connect to host" exit
|
|
expect "*?assword:*"
|
|
send "$password\r"
|
|
expect "$prompt"
|
|
send "file=/etc/sysconfig/network-scripts/ifcfg-eth$interface_id\r"
|
|
expect "$prompt"
|
|
send "hwaddr=\\\$(grep HWADDR \\\$file)\r"
|
|
expect "$prompt"
|
|
send "uuid=\\\$(grep UUID \\\$file)\r"
|
|
expect "$prompt"
|
|
send "echo -e \"\\\$hwaddr\\n\\\$uuid\\nDEVICE=eth$interface_id\\nTYPE=Ethernet\\nONBOOT=yes\\nNM_CONTROLLED=no\\nBOOTPROTO=dhcp\\nPEERDNS=no\" > \\\$file\r"
|
|
expect "$prompt"
|
|
send "sed \"s/GATEWAY=.*/GATEWAY=\"$gateway_ip\"/g\" -i /etc/sysconfig/network\r"
|
|
expect "$prompt"
|
|
send "echo -e \"$nameserver\" > /etc/dnsmasq.upstream\r"
|
|
expect "$prompt"
|
|
send "sed \"s/DNS_UPSTREAM:.*/DNS_UPSTREAM: \\\$(grep \'^nameserver\' /etc/dnsmasq.upstream | cut -d \' \' -f2)/g\" -i /etc/fuel/astute.yaml\r"
|
|
expect "$prompt"
|
|
send "sed -i 's/ONBOOT=no/ONBOOT=yes/g' /etc/sysconfig/network-scripts/ifcfg-eth1\r"
|
|
expect "$prompt"
|
|
send "sed -i 's/NM_CONTROLLED=yes/NM_CONTROLLED=no/g' /etc/sysconfig/network-scripts/ifcfg-eth1\r"
|
|
expect "$prompt"
|
|
send "sed -i 's/BOOTPROTO=dhcp/BOOTPROTO=static/g' /etc/sysconfig/network-scripts/ifcfg-eth1\r"
|
|
expect "$prompt"
|
|
send " echo \"IPADDR=$master_ip_pub_net\" >> /etc/sysconfig/network-scripts/ifcfg-eth1\r"
|
|
expect "$prompt"
|
|
send " echo \"NETMASK=$mask\" >> /etc/sysconfig/network-scripts/ifcfg-eth1\r"
|
|
expect "$prompt"
|
|
send "/sbin/iptables -t nat -A POSTROUTING -s $master_pub_net/24 \! -d $master_pub_net/24 -j MASQUERADE\r"
|
|
expect "$prompt"
|
|
send "/sbin/iptables -I FORWARD 1 --dst $master_pub_net/24 -j ACCEPT\r"
|
|
expect "$prompt"
|
|
send "/sbin/iptables -I FORWARD 1 --src $master_pub_net/24 -j ACCEPT\r"
|
|
expect "$prompt"
|
|
send "service iptables save >/dev/null 2>&1\r"
|
|
expect "$prompt"
|
|
send "dockerctl restart cobbler >/dev/null 2>&1\r"
|
|
expect "$prompt"
|
|
send "service network restart >/dev/null 2>&1\r"
|
|
expect "*OK*"
|
|
expect "$prompt"
|
|
send "dockerctl restart cobbler >/dev/null 2>&1\r"
|
|
expect "$prompt"
|
|
send "dockerctl check cobbler >/dev/null 2>&1\r"
|
|
expect "*ready*"
|
|
expect "$prompt"
|
|
send "logout\r"
|
|
expect "$prompt"
|
|
ENDOFEXPECT
|
|
)
|
|
|
|
# Waiting until the network services are restarted.
|
|
# 5 seconds is optimal time for different operating systems.
|
|
echo -e "\nWaiting until the network services are restarted..."
|
|
sleep 5s
|
|
result_inet=$(
|
|
execute expect << ENDOFEXPECT
|
|
spawn ssh $ssh_options $username@$ip
|
|
expect "connect to host" exit
|
|
expect "*?assword:*"
|
|
send "$password\r"
|
|
expect "$prompt"
|
|
send "for i in {1..5}; do ping -c 2 google.com || ping -c 2 wikipedia.com || sleep 2; done\r"
|
|
expect "*icmp*"
|
|
expect "$prompt"
|
|
send "logout\r"
|
|
expect "$prompt"
|
|
ENDOFEXPECT
|
|
)
|
|
|
|
# When you are launching command in a sub-shell, there are issues with IFS (internal field separator)
|
|
# and parsing output as a set of strings. So, we are saving original IFS, replacing it, iterating over lines,
|
|
# and changing it back to normal
|
|
#
|
|
# http://blog.edwards-research.com/2010/01/quick-bash-trick-looping-through-output-lines/
|
|
OIFS="${IFS}"
|
|
NIFS=$'\n'
|
|
IFS="${NIFS}"
|
|
|
|
for line in $result_inet; do
|
|
IFS="${OIFS}"
|
|
if [[ $line == *icmp_seq* ]]; then
|
|
IFS="${NIFS}"
|
|
echo "OK"
|
|
return 0;
|
|
fi
|
|
IFS="${NIFS}"
|
|
done
|
|
print_no_internet_connectivity_banner
|
|
return 1
|
|
}
|
|
|
|
print_no_internet_connectivity_banner() {
|
|
echo "FAIL"
|
|
echo "############################################################"
|
|
echo "# WARNING: some of the Fuel features will not be supported #"
|
|
echo "# because there is no Internet connectivity #"
|
|
echo "############################################################"
|
|
}
|
|
|