141c1273f5
Change-Id: If7201310e58bd451b965821ac80f466714c2a684
351 lines
8.2 KiB
Bash
Executable File
351 lines
8.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
shopt -s nocasematch
|
|
|
|
SMITHY_NAME=$(readlink -f "$0")
|
|
cd "$(dirname "$0")"
|
|
|
|
VERBOSE="${VERBOSE:-0}"
|
|
PY2RPM_CMD="$PWD/tools/py2rpm"
|
|
|
|
YUM_OPTS="--assumeyes --nogpgcheck"
|
|
PIP_CMD=""
|
|
PIP_OPTS=""
|
|
RPM_OPTS=""
|
|
CURL_OPTS=""
|
|
PACKAGES=""
|
|
PACKAGE_NAMES=""
|
|
CONFLICTS=""
|
|
|
|
if [ "$VERBOSE" == "0" ]; then
|
|
YUM_OPTS="$YUM_OPTS -q"
|
|
PIP_OPTS="-q"
|
|
RPM_OPTS="-q"
|
|
CURL_OPTS="-s"
|
|
fi
|
|
|
|
# Source in our variables (or overrides)
|
|
source ".anvilrc"
|
|
if [ -n "$SUDO_USER" ]; then
|
|
USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6)
|
|
if [ -n "$USER_HOME" ]; then
|
|
HOME_RC="${USER_HOME}/.anvilrc"
|
|
if [ -f "$HOME_RC" ]; then
|
|
source "$HOME_RC"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$BOOT_FILES" ]; then
|
|
BOOT_FN=".anvil_bootstrapped"
|
|
BOOT_FILES="${PWD}/$BOOT_FN"
|
|
fi
|
|
|
|
conflicts() {
|
|
local rpm_name=$1
|
|
if [ -n "$rpm_name" ]; then
|
|
CONFLICTS="$CONFLICTS $rpm_name"
|
|
fi
|
|
}
|
|
|
|
remove_conflicts() {
|
|
if [ -z "$CONFLICTS" ]; then
|
|
return 0
|
|
fi
|
|
echo "Removing conflicting packages: $CONFLICTS"
|
|
for rpm_name in $CONFLICTS; do
|
|
if [ -n $rpm_name ]; then
|
|
yum erase $YUM_OPTS $rpm_name
|
|
fi
|
|
done
|
|
}
|
|
|
|
find_pip()
|
|
{
|
|
if [ -n "$PIP_CMD" ]; then
|
|
return
|
|
fi
|
|
# Handle how RHEL likes to rename it.
|
|
PIP_CMD=""
|
|
for name in pip pip-python; do
|
|
if which "$name" &>/dev/null; then
|
|
PIP_CMD=$name
|
|
break
|
|
fi
|
|
done
|
|
if [ -z "$PIP_CMD" ]; then
|
|
echo "pip or pip-python not found"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
rpm_is_installed()
|
|
{
|
|
local name="$(basename "$1")"
|
|
rpm $RPM_OPTS "${name%.rpm}" &>/dev/null
|
|
}
|
|
|
|
cache_and_install_rpm_url()
|
|
{
|
|
url=${1:?"Error: rpm uri is undefined!"}
|
|
cachedir=${RPM_CACHEDIR:-'/tmp'}
|
|
rpm=$(basename $url)
|
|
if rpm_is_installed "$rpm"; then
|
|
return
|
|
fi
|
|
if [ ! -f "$cachedir/$rpm" ]; then
|
|
echo "Downloading $rpm to $cachedir..."
|
|
curl $CURL_OPTS $url -o "$cachedir/$rpm" || return 1
|
|
fi
|
|
install_rpm "$cachedir/$rpm"
|
|
return $?
|
|
}
|
|
|
|
yum_install()
|
|
{
|
|
local rpm_path=$1
|
|
output=$(yum install $YUM_OPTS "$rpm_path" 2>&1)
|
|
rc=$?
|
|
if [ -n "$output" ]; then
|
|
if [[ ! "$output" =~ "Nothing to do" ]]; then
|
|
echo $output
|
|
fi
|
|
fi
|
|
if [ "$rc" != "0" ]; then
|
|
if [[ "$output" =~ "Nothing to do" ]]; then
|
|
# Not really a problem.
|
|
return 0
|
|
fi
|
|
fi
|
|
return $rc
|
|
}
|
|
|
|
install_rpm()
|
|
{
|
|
local rpm_path=$1
|
|
local py_name=$2
|
|
local always_build=$3
|
|
if [ -n "$rpm_path" -a -z "$always_build" ]; then
|
|
yum_install "$rpm_path"
|
|
if rpm_is_installed "$rpm_path"; then
|
|
return 0
|
|
fi
|
|
fi
|
|
if [ -z "$py_name" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# RPM is not available. Try to build it on fly
|
|
# First download it.
|
|
pip_tmp_dir=$(mktemp -d)
|
|
find_pip
|
|
pip_opts="$PIP_OPTS -U -I"
|
|
$PIP_CMD install $pip_opts "$py_name" --download "$pip_tmp_dir"
|
|
|
|
# Now build it
|
|
echo "Building RPM for $py_name"
|
|
rpm_names=$("$PY2RPM_CMD" "$pip_tmp_dir/"* 2>/dev/null |
|
|
awk '/^Wrote: /{ print $2 }' | grep -v '.src.rpm' | sort -u | grep -v "python-distribute")
|
|
rm -rf "$pip_tmp_dir"
|
|
if [ -z "$rpm_names" ]; then
|
|
echo "No binary RPM was built for $py_name"
|
|
return 1
|
|
fi
|
|
for pkg in $rpm_names; do
|
|
echo "Installing RPM $pkg"
|
|
if [ -f "$pkg" ]; then
|
|
yum_install "$pkg"
|
|
fi
|
|
done
|
|
}
|
|
|
|
bootstrap_epel()
|
|
{
|
|
[ -z "$EPEL_RPM_URL" ] && return 0
|
|
cache_and_install_rpm_url $EPEL_RPM_URL
|
|
return $?
|
|
}
|
|
|
|
bootstrap_packages()
|
|
{
|
|
[ -z "$PACKAGES" ] && return 0
|
|
for pkg in $PACKAGES; do
|
|
local rpm_name=$(echo $pkg | cut -d: -f1)
|
|
local py_name=$(echo $pkg | cut -d: -f2)
|
|
local always_build=$(echo $pkg | cut -d: -f3)
|
|
install_rpm "$rpm_name" "$py_name" "$always_build"
|
|
install_status=$?
|
|
if [ "$install_status" != 0 ]; then
|
|
echo "Error: Installation of package '$rpm_name' failed!"
|
|
return "$install_status"
|
|
fi
|
|
done
|
|
}
|
|
|
|
require()
|
|
{
|
|
local rpm_name=$1
|
|
local py_name=$2
|
|
local always_build=$3
|
|
if [ -z "$rpm_name" -a -z "$py_name" ]; then
|
|
echo "Please specify at RPM or Python package name"
|
|
exit 1
|
|
fi
|
|
PACKAGES="$PACKAGES $rpm_name:$py_name:$always_build"
|
|
PACKAGE_NAMES="$PACKAGE_NAMES $rpm_name"
|
|
}
|
|
|
|
needs_bootstrap()
|
|
{
|
|
$BOOTSTRAP && return 0
|
|
checksums=$(get_checksums)
|
|
for i in $BOOT_FILES; do
|
|
if [ -f $i ]; then
|
|
contents=`cat $i`
|
|
[ "$contents" = "$checksums" ] && return 1
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
get_checksums()
|
|
{
|
|
if [ ! -f "$BSCONF_FILE" ]; then
|
|
return 1
|
|
fi
|
|
# Used to tell if the file have changed
|
|
echo $(md5sum "$BSCONF_FILE")
|
|
}
|
|
|
|
run_smithy()
|
|
{
|
|
PYTHON=`which python`
|
|
exec $PYTHON anvil $ARGS
|
|
}
|
|
|
|
puke()
|
|
{
|
|
cleaned_force=$(echo $FORCE | sed -e 's/\([A-Z]\)/\L\1/g;s/\s//g')
|
|
if [[ "$cleaned_force" == "yes" ]]; then
|
|
run_smithy
|
|
else
|
|
echo "To run anyway set FORCE=yes and rerun." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
## Identify which bootstrap configuration file to use: either set
|
|
## explicitly (BSCONF_FILE) or determined based on the os distribution:
|
|
BSCONF_DIR=${BSCONF_DIR:-$(dirname $(readlink -f "$0"))/tools/bootstrap}
|
|
get_os_info(){
|
|
OS=`uname`
|
|
if [ "${OS}" = "Linux" ] ; then
|
|
if [ -f /etc/redhat-release ] ; then
|
|
PKG="rpm"
|
|
OSNAME=`cat /etc/redhat-release`
|
|
OSDIST=`cat /etc/redhat-release | sed -e 's/release.*$//g;s/\s//g'`
|
|
PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
|
|
RELEASE=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
|
|
elif [ -f /etc/debian_version ] ; then
|
|
PKG="deb"
|
|
OSDIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F= '{ print $2 }'`
|
|
PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F= '{ print $2 }'`
|
|
RELEASE=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F= '{ print $2 }'`
|
|
OSNAME="$OSDIST $RELEASE ($PSUEDONAME)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
get_os_info
|
|
|
|
if [ -z "$BSCONF_FILE" ]; then
|
|
BSCONF_FILE="$BSCONF_DIR/$OSDIST"
|
|
fi
|
|
|
|
ARGS=""
|
|
BOOTSTRAP=false
|
|
|
|
if [ -f "$BSCONF_FILE" ]; then
|
|
source $BSCONF_FILE
|
|
fi
|
|
|
|
# Export these immediatly so that anvil can know about them and it will
|
|
# avoid removing them.
|
|
export REQUIRED_PACKAGES="$PACKAGE_NAMES"
|
|
export CONFLICTING_PACKAGES="$CONFLICTS"
|
|
|
|
# Ad-hoc getopt to handle long opts.
|
|
#
|
|
# Smithy opts are consumed while those to anvil are copied through.
|
|
while [ ! -z $1 ]; do
|
|
case "$1" in
|
|
'--bootstrap')
|
|
BOOTSTRAP=true
|
|
shift
|
|
;;
|
|
'--force')
|
|
FORCE=yes
|
|
shift
|
|
;;
|
|
*)
|
|
ARGS="$ARGS $1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if ! needs_bootstrap; then
|
|
run_smithy
|
|
elif ! $BOOTSTRAP; then
|
|
echo "This system needs to be updated in order to run anvil!" >&2
|
|
echo "Running 'sudo $SMITHY_NAME --bootstrap' will attempt to do so." >&2
|
|
exit 1
|
|
fi
|
|
|
|
## Bootstrap smithy
|
|
if [ "$(id -u)" != "0" ]; then
|
|
echo "You must run '$SMITHY_NAME --bootstrap' with root privileges!" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$BSCONF_FILE" ]; then
|
|
echo "Anvil has not been tested on distribution '$OSNAME'" >&2
|
|
puke
|
|
fi
|
|
|
|
MIN_RELEASE=${MIN_RELEASE:?"Error: MIN_RELEASE is undefined!"}
|
|
SHORTNAME=${SHORTNAME:?"Error: SHORTNAME is undefined!"}
|
|
|
|
BC_OK=$(echo "$RELEASE < $MIN_RELEASE" | bc)
|
|
if [ "$BC_OK" == "1" ]; then
|
|
echo "This script must be run on $SHORTNAME $MIN_RELEASE+ and not $SHORTNAME $RELEASE." >&2
|
|
puke
|
|
fi
|
|
|
|
echo "Bootstrapping $SHORTNAME $RELEASE"
|
|
echo "Please wait..."
|
|
remove_conflicts
|
|
|
|
for step in ${STEPS:?"Error: STEPS is undefined!"}; do
|
|
bootstrap_${step}
|
|
if [ $? != 0 ]; then
|
|
echo "Bootstrapping $SHORTNAME $RELEASE failed." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Write the checksums of the bootstrap file
|
|
# which if new requirements are added will cause new checksums
|
|
# and a new dependency install...
|
|
checksum=$(get_checksums)
|
|
for i in $BOOT_FILES; do
|
|
echo -e $checksum > $i
|
|
done
|
|
|
|
mkdir -p -v /etc/anvil /usr/share/anvil
|
|
if [ -n "$SUDO_UID" -a -n "SUDO_GID" ]; then
|
|
chown -c "$SUDO_UID:$SUDO_GID" /etc/anvil /usr/share/anvil
|
|
fi
|
|
|
|
echo "Success! Bootstrapped for $SHORTNAME $RELEASE"
|
|
exit 0
|