Installer auto-detects distro, portable system init

The theme of this commit is to make the install process more
resiliant to differences in distros by testing for specific
features or versions of executables rather than making as many
assumptions just on the distro and release.

* Distro and Release detection (install, Vagrantfile)
  - Added detection logic for distro and release based on
    /etc/os-release which is available on all potential supported
    distros. The --distribution and --release options can be used
    to override detection.
  - Added distro and release checks to ensure values specified are
    for a supported release.
  - Changed some distro checks to use booleans, e.g.
    if $is_centos_7; then ...
  - Added a simple check so if --distribution is specified, it will
    ensure it's at least sane, e.g. centos on debian or debian on
    centos will be caught.
  - In Vagrantfile, removed --distribution and --release options for
    all distro and release combinations.

* Portable Init System Detection and Management (install, centos.sh)
  - Added detection logic for init system type - systemd, Upstart or
    System V in the function systemInitDetect().
  - Added portable init system install in the function
    systemInitInstall() which depends on systemInitDetect(). After
    installing files, enables and starts service.
  - Added portable init system commands in the function
    systemInitCommand() for start, stop, reload, restart and status.
  - Python services don't support systemd but unconditionally install
    scripts for both Upstart and System V. Disabled by passing
    --no-init-script to setup.py for each service.
  - When upgrading, remove all old system init files in /etc/init,
    /etc/init.d, /etc/default and /etc/systemd/system.
  - In centos.sh, removed install of airtime systemd service files
    as it's now handled by install.
  - Created an Upstart .conf for airtime-celery
  - In systemd file for airtime-celery, changed absolute path to
    /usr/local/bin/celery and for centos, the install symlinks
    celery to /usr/local/bin.

* External Dependencies Install (install)
  - For external dependencies, only attempt to install for Debian-
    based distros with apt-get. For centos, a warning is displayed.
  - For systems with apt-get, detect version and if 1.1 or greater,
    use new force options, otherwise use --force-yes option.

* Configuring Apache (install)
  - For Apache, check for centos and use httpd for binary and
    service, otherwise use apache2ctl and apache2.
  - Detect Apache version 2 or better in a more reliable manner.
  - Detect Apache root folder and conf file name by running
    apache2ctl -V or httpd -V as appropriate.
  - Various checks for centos as it doesn't support the Debian
    Apache utilities a2ensite/a2dissite, a2enmod/a2dismod, etc.

* Installing Airtime Services (install)
  - Detect Python version. If less than 2.7.9, install OpenSSL
    support.
  - Prevent installing init files by passing --no-init-script to
    setup.py for each service.
  - Use systemInitInstall to install, enable and start each service
    after setup.py has run.
  - Removed filtering for WEB_USER for files in
    /etc/init/airtime*.template as that is handled in the
    systemInitInstall() function.

* Configuring PHP in Apache (install)
  - Detect PHP conf folder by checking a list of locations rather
    than making assumptions based on the distro and release.

* Configuring PostgreSQL (install)
  - Detects if the airtime user has already been created. If not,
    then creates the user.

* Installing Locales (install)
  - Minor changes to check for centos and prevent from running.
This commit is contained in:
Bill Burton 2017-04-28 11:00:50 -04:00
parent 711238af18
commit 3179651dec
5 changed files with 484 additions and 173 deletions

14
Vagrantfile vendored
View File

@ -40,35 +40,35 @@ Vagrant.configure("2") do |config|
# define all the OS boxes we support # define all the OS boxes we support
config.vm.define "ubuntu-xenial" do |os| config.vm.define "ubuntu-xenial" do |os|
os.vm.box = "bento/ubuntu-16.04" os.vm.box = "bento/ubuntu-16.04"
provision_libretime(os, "ubuntu.sh", installer_args + "--distribution=ubuntu --release=xenial") provision_libretime(os, "ubuntu.sh", installer_args)
end end
config.vm.define "ubuntu-trusty" do |os| config.vm.define "ubuntu-trusty" do |os|
os.vm.box = "bento/ubuntu-14.04" os.vm.box = "bento/ubuntu-14.04"
provision_libretime(os, "ubuntu.sh", installer_args + "--distribution=ubuntu --release=trusty") provision_libretime(os, "ubuntu.sh", installer_args)
end end
config.vm.define "ubuntu" do |os| config.vm.define "ubuntu" do |os|
STDERR.puts 'WARNING: The "ubuntu" option is deprecated. Please migrate to "ubuntu-trusty".' STDERR.puts 'WARNING: The "ubuntu" option is deprecated. Please migrate to "ubuntu-trusty".'
STDERR.puts STDERR.puts
os.vm.box = "ubuntu/trusty64" os.vm.box = "ubuntu/trusty64"
provision_libretime(os, "ubuntu.sh", installer_args + "--distribution=ubuntu --release=trusty") provision_libretime(os, "ubuntu.sh", installer_args)
end end
config.vm.define "debian-jessie" do |os| config.vm.define "debian-jessie" do |os|
os.vm.box = "bento/debian-8.7" os.vm.box = "bento/debian-8.7"
provision_libretime(os, "debian.sh", installer_args + "--distribution=debian --release=jessie") provision_libretime(os, "debian.sh", installer_args)
end end
config.vm.define "debian-wheezy" do |os| config.vm.define "debian-wheezy" do |os|
os.vm.box = "bento/debian-7.11" os.vm.box = "bento/debian-7.11"
provision_libretime(os, "debian.sh", installer_args + "--distribution=debian --release=wheezy") provision_libretime(os, "debian.sh", installer_args)
end end
config.vm.define "debian" do |os| config.vm.define "debian" do |os|
STDERR.puts 'WARNING: The "debian" option is deprecated. Please migrate to "debian-jessie".' STDERR.puts 'WARNING: The "debian" option is deprecated. Please migrate to "debian-jessie".'
STDERR.puts STDERR.puts
os.vm.box = "debian/jessie64" os.vm.box = "debian/jessie64"
provision_libretime(os, "debian.sh", installer_args + "--distribution=debian --release=jessie") provision_libretime(os, "debian.sh", installer_args)
end end
config.vm.define "centos" do |os| config.vm.define "centos" do |os|
os.vm.box = 'centos/7' os.vm.box = 'centos/7'
provision_libretime(os, "centos.sh", installer_args + "--ignore-dependencies --distribution=centos --web-user=apache --selinux") provision_libretime(os, "centos.sh", installer_args + "--selinux")
end end
def provision_libretime(config, prepare_script, installer_args) def provision_libretime(config, prepare_script, installer_args)

602
install
View File

@ -62,7 +62,7 @@ showversion () {
exit 0 exit 0
} }
web_user="www-data" web_user=""
web_root="" web_root=""
web_port="80" web_port="80"
in_place="f" in_place="f"
@ -80,7 +80,7 @@ _q=0
upgrade="f" upgrade="f"
dist="" dist=""
code="" code=""
apache_bin="apache2" apache_bin=""
function verbose() { function verbose() {
@ -95,9 +95,11 @@ function loud() {
fi fi
} }
# Evaluate commands silently if quiet # Evaluate commands silently if quiet.
# If not quiet, output command if verbose.
function loudCmd() { function loudCmd() {
if [[ ${_q} -eq 0 ]]; then if [[ ${_q} -eq 0 ]]; then
verbose "$@"
eval $@ eval $@
else else
eval $@ > /dev/null eval $@ > /dev/null
@ -116,6 +118,225 @@ function checkCommandExists() {
set -e set -e
} }
# Function to determine if systemd, Upstart or System V Init is the active
# init system. All the newer supported distros use systemd out-of-the-box but
# a sysadmin could have installed an alternative init compatibility package.
# As a result, making assumptions based on the distribution and release is
# not a good idea. The detection works as follows:
# 1. Get the process name where PID=1 and follow any symlinks.
# 2. Look up that path in the appropriate package manager to get the name
# of the package that process is part of.
# See https://unix.stackexchange.com/questions/196166/how-to-find-out-if-a-system-uses-sysv-upstart-or-systemd-initsystem
has_systemd_init=false
has_upstart_init=false
has_systemv_init=false
function systemInitDetect() {
verbose "\nDetecting init system type ..."
# Get the path of the command where pid=1 following any symlinks
pid_1_path=$(readlink --canonicalize -n /proc/1/exe)
# returns '/sbin/init' (Debian Wheezy & Ubuntu Trusty)
# returns '(/usr)?/lib/systemd/systemd' (Debian Jessie, Ubuntu Xenial, CentOS 7)
verbose "Detected path to PID=1 process: $pid_1_path"
# Get package of PID=1 path as it identifies the init system
pid_1_package=$(dpkg -S $pid_1_path 2>/dev/null ||
rpm --qf '%{name}\n' -qf $pid_1_path 2>/dev/null)
verbose "Detected package name for PID=1 process: $pid_1_package"
case "${pid_1_package-$pid_1_path}" in
*systemd*) has_systemd_init=true; verbose "Detected init system type: systemd" ;;
*upstart*) has_upstart_init=true; verbose "Detected init system type: Upstart" ;;
*sysvinit*) has_systemv_init=true; verbose "Detected init system type: System V" ;;
*) echo "ERROR: Unable to detect init system using package or path of PID=1 process!" >&2
exit 1
;;
esac
return 0
}
# Function to wrap installation of services for systemd, Upstart and System V
# depending on which one was detected by the systemInitDetect() function.
# Service file is copied from a known location and installed into the system.
# In the process, filtering is performed for the userid if appropriate.
# If required, the service is enabled; then it is started.
# Usage:
# systemInitInstall service-name [user]
function systemInitInstall() {
local service_name="$1"
local user="$2"
local source_base_path=""
local source_path=""
local target_path=""
local source_config_path=""
local target_config_path=""
local python_source_path="${SCRIPT_DIR-$PWD}/python_apps"
verbose "\n * Installing service $service_name ..."
if $has_systemd_init; then
# TODO: move .service files under python_apps/.../install/systemd
source_path="${SCRIPT_DIR-$PWD}/installer/systemd/${service_name}.service"
target_path="/etc/systemd/system/${service_name}.service"
if [[ ! -e $source_path ]]; then
echo "$0:${FUNCNAME}(): ERROR: service \"$service_name\" with source path \"$source_path\" does not exist!" >&2
exit 1
fi
# Stop and disable the service if it already exists
if [[ -e $target_path ]]; then
verbose "Service $service_name already exists - stopping and disabling."
loudCmd "systemctl disable ${service_name}.service"
loudCmd "systemctl stop ${service_name}.service"
fi
# If no user defined, then just copy, otherwise filter
if [[ -z $user ]]; then
loudCmd "cp $source_path $target_path"
else
sed -e "s/User=.*/User=${user}/" \
-e "s/Group=.*/Group=${user}/" $source_path > $target_path
fi
chmod 0644 $target_path
chown root:root $target_path
verbose "Service ${service_name} installed into ${target_path}"
# Enable and start the service
loudCmd "systemctl enable ${service_name}.service"
loudCmd "systemctl start ${service_name}.service"
verbose "Service ${service_name} enabled and started"
elif $has_upstart_init; then
case "$service_name" in
airtime_analyzer)
source_path="${python_source_path}/${service_name}/install/upstart/${service_name}.conf"
target_path="/etc/init/${service_name}.conf"
user=${user:-$web_user}
;;
airtime-celery)
source_path="${python_source_path}/${service_name}/install/upstart/${service_name}.conf"
target_path="/etc/init/${service_name}.conf"
user=""
;;
airtime-liquidsoap|airtime-playout)
source_path="${python_source_path}/pypo/install/upstart/${service_name}.conf.template"
target_path="/etc/init/${service_name}.conf"
user=${user:-$web_user}
;;
esac
if [[ ! -e $source_path ]]; then
echo "$0:${FUNCNAME}(): ERROR: service \"$service_name\" with source path \"$source_path\" does not exist!" >&2
exit 1
fi
# Stop the service if it already exists
if [[ -e $target_path ]]; then
verbose "Service $service_name already exists - stopping."
loudCmd "service ${service_name} stop"
fi
# If no user defined, then just copy, otherwise filter
if [[ -z $user ]]; then
loudCmd "cp $source_path $target_path"
else
sed -e "s/WEB_USER/${user}/g" \
-e "/^set[gu]id/{s/www-data/${user}/}" $source_path > $target_path
fi
chmod 0644 $target_path
chown root:root $target_path
verbose "Service ${service_name} installed into ${target_path}"
loudCmd "initctl check-config $service_name"
# Start the service
loudCmd "service ${service_name} start"
verbose "Service ${service_name} started"
elif $has_systemv_init; then
case "$service_name" in
airtime_analyzer)
source_path="${python_source_path}/${service_name}/install/sysvinit/${service_name}"
target_path="/etc/init.d/${service_name}"
user=${user:-$web_user}
;;
airtime-celery)
source_path="${python_source_path}/${service_name}/install/initd/${service_name}"
target_path="/etc/init.d/${service_name}"
source_config_path="${python_source_path}/${service_name}/install/conf/${service_name}"
target_config_path="/etc/default/${service_name}"
user=""
;;
airtime-liquidsoap|airtime-playout)
source_path="${python_source_path}/pypo/install/sysvinit/${service_name}"
target_path="/etc/init.d/${service_name}"
user=${user:-$web_user}
;;
esac
if [[ ! -e $source_path ]]; then
echo "$0:${FUNCNAME}(): ERROR: service \"$service_name\" with source path \"$source_path\" does not exist!" >&2
exit 1
fi
# Stop the service if it already exists
if [[ -e $target_path ]]; then
verbose "Service $service_name already exists - stopping."
loudCmd "invoke-rc.d $service_name stop"
fi
# If no user defined, then just copy, otherwise filter
if [[ -z $user ]]; then
loudCmd "cp $source_path $target_path"
[[ -n $source_config_path ]] &&
loudCmd "cp $source_config_path $target_config_path"
else
sed -e "/^USERID/{s/www-data/${user}/}" \
-e "/^GROUPID/{s/www-data/${user}/}" $source_path > $target_path
fi
chmod 0644 $target_path
chown root:root $target_path
if [[ -n $target_config_path ]]; then
chmod 0644 $target_config_path
chown root:root $target_config_path
fi
verbose "Service ${service_name} installed into ${target_path}"
# Create symlinks for the appropriate runlevels
loudCmd "update-rc.d $service_name defaults"
# Start the service
loudCmd "invoke-rc.d $service_name start"
verbose "Service ${service_name} enabled and started"
fi
return 0
}
# Function to wrap different systemd vs. Upstart init commands depending
# on which init system has been detected. Syntax is similar to systemctl.
# Usage:
# systemInitCommand _command_ [service-name ...]
# Where _command_ is one of: start, stop, status, reload, restart
# enable, disable and either daemon-reload or reload-configuration.
function systemInitCommand() {
local command=$1; shift
case "$command" in
start|stop|status|reload|restart)
if $has_systemd_init; then
loudCmd "systemctl $command $@"
elif $has_upstart_init; then
for svc_name in $@; do
loudCmd "service $svc_name $command"
done
elif $has_systemv_init; then
for svc_name in $@; do
loudCmd "invoke-rc.d $svc_name $command"
done
fi
;;
enable|disable) # TODO: REMOVE
$has_systemd_init &&
loudCmd "systemctl $command $1.service"
if $has_systemv_init; then
if [[ "$command" = "enable" ]]
then loudCmd "update-rc.d $1 defaults"
else loudCmd "update-rc.d $1 enable"
fi
fi
;;
daemon-reload|reload-configuration)
$has_systemd_init &&
loudCmd "systemctl daemon-reload"
$has_upstart_init &&
loudCmd "initctl reload-configuration"
;;
*) echo -e "$0:${FUNCNAME}(): ERROR: command \"$command\" is not supported!" >&2
exit 1
;;
esac
return 0
}
while :; do while :; do
case "$1" in case "$1" in
--help) --help)
@ -309,35 +530,137 @@ echo "| |___| || \_\ \ | \/\ ___/| | | | Y Y \ ___/ "
echo "|_______ \__||___ /__| \___ >____| |__|__|_| /\___ >" echo "|_______ \__||___ /__| \___ >____| |__|__|_| /\___ >"
echo -e " \/ \/ \/ \/ \/\n" echo -e " \/ \/ \/ \/ \/\n"
if [ "$dist" = "centos" ]; then echo -e "Detecting distribution and release ..."
if [ -e /etc/os-release ]; then
# Access $ID, $VERSION_ID and $PRETTY_NAME
source /etc/os-release
echo "Detected distribution id: $ID"
echo "Detected distribution release id: $VERSION_ID"
echo "Detected distribution description: $PRETTY_NAME"
else
ID=unknown
VERSION_ID=unknown
PRETTY_NAME="Unknown distribution and release"
echo "WARNING: /etc/os-release configuration not found. Unable to detect distribution." >&2
if [ -z "$dist" -o -z "$code" ]; then
echo "ERROR: One or both of --distribution and --release options were not specified." >&2
echo "This is an unsupported distribution and/or version!" >&2
exit 1
fi
fi
# Validate --distribution parameter has a sane value for this OS.
if [ -n "$dist" ]; then
dist=${dist,,}
verbose "Checking --distribution \"$dist\" to ensure it has a sane value."
# If $ID detected above does not match parameter, then do some checking
if [ "$dist" != "$ID" ]; then
verbose "Detected distribution \"$ID\" does not match specified one of \"$dist\". Checking ..."
case "$dist" in
centos|rhel) pkg_installer=/usr/bin/yum; verbose "Detected yum package installer" ;;
debian|ubuntu) pkg_installer=/usr/bin/apt-get; verbose "Detected apt-get package installer" ;;
*) echo "ERROR: the value \"$dist\" specified for --distribution is unsupported." >&2
exit 1
;;
esac
if [ ! -x "$pkg_installer" ]; then
echo "ERROR: The value \"$dist\" specified for --distribution does not appear compatible!" >&2
exit 1
fi
fi
fi
# Validate the distribution and release is a supported one; set boolean flags.
is_debian_dist=false
is_debian_jessie=false
is_debian_wheezy=false
is_ubuntu_dist=false
is_ubuntu_xenial=false
is_ubuntu_trusty=false
is_centos_dist=false
is_centos_7=false
# Use specified distribution and release or detected otherwise.
dist="${dist:-$ID}"
code="${code:-$VERSION_ID}"
code="${code,,}"
verbose "Validating dist-code: ${dist}-${code}"
case "${dist}-${code}" in
ubuntu-16.04|ubuntu-xenial)
code="xenial"
is_ubuntu_dist=true
is_ubuntu_xenial=true
;;
ubuntu-14.04|ubuntu-trusty)
code="trusty"
is_ubuntu_dist=true
is_ubuntu_trusty=true
;;
debian-8|debian-jessie)
code="jessie"
is_debian_dist=true
is_debian_jessie=true
;;
debian-7|debian-wheezy)
code="wheezy"
is_debian_dist=true
is_debian_wheezy=true
;;
centos-7)
is_centos_dist=true
is_centos_7=true
;;
*)
echo -e "ERROR: Distribution \"$PRETTY_NAME\" is not supported with \"${dist}-${code}\"!" >&2
exit 1
;;
esac
verbose "Using distribution id \"$dist\", release code \"$code\""
# Detect init system type
systemInitDetect
if $is_centos_dist; then
apache_bin="httpd" apache_bin="httpd"
apache_service="httpd"
web_user="${web_user:-apache}"
else
apache_bin="apache2ctl"
apache_service="apache2"
web_user="${web_user:-www-data}"
fi fi
if [ "$ignore_dependencies" = "f" ]; then if [ "$ignore_dependencies" = "f" ]; then
set +e set +e
if [ -z "${dist}" ]; then
loudCmd "apt-get -y --force-yes install lsb-release"
dist=`lsb_release -ds | awk '{print tolower($1);}'`
code=`lsb_release -cs`
fi
loud "\n-----------------------------------------------------" loud "\n-----------------------------------------------------"
loud " * Installing External Dependencies * " loud " * Installing External Dependencies * "
loud "-----------------------------------------------------" loud "-----------------------------------------------------"
verbose "\n * Reading requirements-${dist,,}-${code,,}.apt..." if [ -x /usr/bin/apt-get ]; then
loudCmd "apt-get update" verbose "\n * Reading requirements-${dist}-${code}.apt..."
if [ -f ${SCRIPT_DIR}/installer/lib/requirements-${dist,,}-${code,,}.apt ]; then loudCmd "apt-get update"
if [ ${dist,,} == "ubuntu" ] && [ ${code,,} == "xenial" ]; then package_list_file="${SCRIPT_DIR}/installer/lib/requirements-${dist}-${code}.apt"
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m --allow-downgrades --allow-remove-essential --allow-change-held-packages install $(grep -vE '^\s*#' ${SCRIPT_DIR}/installer/lib/requirements-${dist,,}-${code,,}.apt | tr '\n' ' ')" if [ ! -f "$package_list_file" ]; then
else echo "ERROR: package file does not exist: $package_list_file" >&2
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m --force-yes install $(grep -vE '^\s*#' ${SCRIPT_DIR}/installer/lib/requirements-${dist,,}-${code,,}.apt | tr '\n' ' ')" exit 1
fi
# For apt-get version 1.1 or higher, --force-yes is deprecated so use new options.
apt_force_options="--allow-downgrades --allow-remove-essential --allow-change-held-packages"
# Get apt-get version by returning the 2nd parameter from the 1st line of output
apt_version=$(apt-get --version |awk 'NR == 1 { print $2 }')
# returns: 0.9.7.9 (Debian Wheezy)
# returns: 1.0.1ubuntu2 (Ubuntu Trusty)
# returns: 1.0.9.8.4 (Debian Jessie)
# returns: 1.2.9 (Ubuntu Xenial)
verbose "Detected apt-get version as: $apt_version"
apt_version_formatted=$(awk 'BEGIN {FS = "."} {printf "%03d.%03d\n", $1,$2}' <<< $apt_version)
[[ "$apt_version_formatted" < "001.001" ]] && apt_force_options="--force-yes"
verbose "Using apt-get force options: $apt_force_options"
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m ${apt_force_options} install $(grep -vE '^\s*#' $package_list_file | tr '\n' ' ')"
if [ "$in_place" = "t" ]; then
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m install git"
fi fi
else else
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m --force-yes install $(grep -vE '^\s*#' ${SCRIPT_DIR}/installer/lib/requirements-ubuntu-trusty.apt | tr '\n' ' ')" echo "WARNING: installing dependencies is not supported for this distribution" >&2
fi
if [ "$in_place" = "t" ]; then
loudCmd "DEBIAN_FRONTEND=noninteractive apt-get -y -m --force-yes install git"
fi fi
set -e set -e
else else
@ -371,10 +694,7 @@ if [ -f /etc/airtime/airtime.conf ]; then
set +e set +e
verbose "Stopping airtime services..." verbose "Stopping airtime services..."
loudCmd "service airtime-playout stop" systemInitCommand stop airtime_analyzer airtime-celery airtime-playout airtime-liquidsoap
loudCmd "service airtime-celery stop"
loudCmd "service airtime_analyzer stop"
loudCmd "service airtime-liquidsoap stop"
verbose "...Done" verbose "...Done"
echo "Looks like you have an old version of Airtime. Your current /etc/airtime/airtime.conf \ echo "Looks like you have an old version of Airtime. Your current /etc/airtime/airtime.conf \
@ -385,12 +705,15 @@ will be moved to /etc/airtime/airtime.conf.tmp"
rm -rf /usr/lib/airtime/ rm -rf /usr/lib/airtime/
fi fi
rm /etc/init.d/airtime-* rm -f /etc/init.d/airtime*
rm -f /etc/init/airtime*
rm -f /etc/default/airtime-celery
rm -f /etc/systemd/system/airtime*
if [ "$apache" = "t" ]; then if [ "$apache" = "t" ]; then
# If the user selects an "in-place" install or passes in a web root, # If the user selects an "in-place" install or passes in a web root,
# we need to replace the old apache airtime.conf # we need to replace the old apache airtime.conf
rm /etc/apache2/sites-available/airtime.conf rm /etc/apache2/sites-available/airtime.conf /etc/apache2/sites-enabled/airtime.conf
fi fi
if [ -d /usr/share/airtime -a web_root = /usr/share/airtime ]; then if [ -d /usr/share/airtime -a web_root = /usr/share/airtime ]; then
@ -432,17 +755,31 @@ if [ "$apache" = "t" ]; then
loud "\n-----------------------------------------------------" loud "\n-----------------------------------------------------"
loud " * Configuring Apache * " loud " * Configuring Apache * "
loud "-----------------------------------------------------" loud "-----------------------------------------------------"
apache_sitedir="/etc/apache2/sites-available/" # Detect Apache root folder, e.g. /etc/apache2 or /etc/httpd
if [ "$dist" = "centos" ]; then eval $($apache_bin -V |awk '/HTTPD_ROOT|SERVER_CONFIG_FILE/ { print $2 }')
apache_sitedir="/etc/httpd/conf.d/" apache_conf="${HTTPD_ROOT}/${SERVER_CONFIG_FILE}"
verbose "Detected Apache root folder is: ${HTTPD_ROOT}"
if [[ ! -e $apache_conf ]]; then
echo -e "ERROR: Apache binary \"$apache_bin\" points to a non-existent file \"$apache_conf\""
exit 1
fi fi
verbose "Detected Apache primary .conf file is: ${apache_conf}"
if [[ -d ${HTTPD_ROOT}/sites-available ]]; then # debian & ubuntu
apache_sitedir="${HTTPD_ROOT}/sites-available/"
elif [[ -d ${HTTPD_ROOT}/conf.d ]]; then # centos
apache_sitedir="${HTTPD_ROOT}/conf.d/"
else
echo -e "ERROR: unknown location of Apache sites-available or virtual host directory!" >&2
exit 1
fi
verbose "Detected Apache sites configuration folder: ${apache_sitedir}"
set +e set +e
$apache_bin -v | grep "2\.4" > /dev/null # Parse: Server version: Apache/2.2.22 (Ubuntu) -> 2
apacheversion=$? apache_major_version=$($apache_bin -v |awk -F'[ /.]+' 'NR == 1 { print $4 }')
set -e set -e
if [ "$apacheversion" != "1" ]; then if [[ "$apache_major_version" -ge 2 ]]; then
airtimeconfigfile="airtime.conf" airtimeconfigfile="airtime.conf"
oldconfigfile="airtime-vhost.conf" oldconfigfile="airtime-vhost.conf"
else else
@ -460,9 +797,9 @@ if [ "$apache" = "t" ]; then
if [ "$web_port" != "80" ]; then if [ "$web_port" != "80" ]; then
listen_port="Listen ${web_port}" listen_port="Listen ${web_port}"
fi fi
apache_template_file=${SCRIPT_DIR}/installer/apache/airtime-vhost-2.4 apache_template_file=${SCRIPT_DIR}/installer/apache/airtime-vhost-2.4
if [ "$apacheversion" = "1" ]; then if [[ "$apache_major_version" -eq 1 ]]; then
# fall back to apache 1 config # fall back to apache 1 config
apache_template_file=${SCRIPT_DIR}/installer/apache/airtime-vhost apache_template_file=${SCRIPT_DIR}/installer/apache/airtime-vhost
fi fi
@ -472,15 +809,14 @@ if [ "$apache" = "t" ]; then
-e "s@WEB_ROOT@${web_root}@g" \ -e "s@WEB_ROOT@${web_root}@g" \
${apache_template_file} > ${apache_sitedir}${airtimeconfigfile} ${apache_template_file} > ${apache_sitedir}${airtimeconfigfile}
if [ "$dist" != "centos" ]; then # The a2ensite/a2dissite utilities are not available on CentOS
if [[ -x /usr/sbin/a2ensite ]]; then
loudCmd "a2dissite 000-default" loudCmd "a2dissite 000-default"
fi # If Airtime was previously installed with apt, the vhost file name is different,
# If Airtime was previously installed with apt, the vhost file name is different, # so we need to specifically disable it.
# so we need to specifically disable it. if [ -f "/etc/apache2/sites-available/${oldconfigfile}" ]; then
if [ -f "/etc/apache2/sites-available/${oldconfigfile}" ]; then loudCmd "a2dissite airtime-vhost"
loudCmd "a2dissite airtime-vhost" fi
fi
if [ "$dist" != "centos" ]; then
loudCmd "a2ensite airtime" loudCmd "a2ensite airtime"
fi fi
else else
@ -508,10 +844,8 @@ if [ "$icecast" = "t" ]; then
else else
icecast_unit_name="icecast" icecast_unit_name="icecast"
fi fi
set +e
# restart in case icecast was already started (like is the case on debian) # restart in case icecast was already started (like is the case on debian)
loudCmd "service ${icecast_unit_name} restart" systemInitCommand restart ${icecast_unit_name}
set -e
verbose "...Done" verbose "...Done"
fi fi
@ -523,13 +857,13 @@ verbose "\n * Installing necessary python services..."
loudCmd "pip install setuptools --upgrade" loudCmd "pip install setuptools --upgrade"
verbose "...Done" verbose "...Done"
# Ubuntu trusty needs a workaround for python version SSL downloads # Ubuntu Trusty and Debian Wheezy needs a workaround for python version SSL downloads
# This affects all python installs where python < 2.7.9 # This affects all python installs where python < 2.7.9
use_pyopenssl="" python_version=$(python --version 2>&1 | awk '{ print $2 }')
if [ "$dist" != "debian" ] || [ "$code" = "wheezy" ]; then verbose "Detected Python version: $python_version"
use_pyopenssl="t" # Convert version so each segment is zero padded for easy comparison
fi python_version_formatted=$(awk 'BEGIN {FS = "."} {printf "%03d.%03d.%03d\n", $1,$2,$3}' <<< $python_version)
if [ "$use_pyopenssl" = "t" ]; then if [[ "$python_version_formatted" < "002.007.009" ]]; then
verbose "\n * Installing pyOpenSSL and ca db for SNI support..." verbose "\n * Installing pyOpenSSL and ca db for SNI support..."
loudCmd "pip install pyOpenSSL cryptography idna certifi --upgrade" loudCmd "pip install pyOpenSSL cryptography idna certifi --upgrade"
verbose "...Done" verbose "...Done"
@ -550,76 +884,34 @@ loudCmd "python ${AIRTIMEROOT}/python_apps/api_clients/setup.py install --instal
verbose "...Done" verbose "...Done"
verbose "\n * Installing pypo and liquidsoap..." verbose "\n * Installing pypo and liquidsoap..."
loudCmd "python ${AIRTIMEROOT}/python_apps/pypo/setup.py install --install-scripts=/usr/bin" loudCmd "python ${AIRTIMEROOT}/python_apps/pypo/setup.py install --install-scripts=/usr/bin --no-init-script"
systemInitInstall airtime-liquidsoap $web_user
systemInitInstall airtime-playout $web_user
verbose "...Done" verbose "...Done"
verbose "\n * Installing airtime-celery..." verbose "\n * Installing airtime-celery..."
loudCmd "python ${AIRTIMEROOT}/python_apps/airtime-celery/setup.py install" loudCmd "python ${AIRTIMEROOT}/python_apps/airtime-celery/setup.py install --no-init-script"
# Make the airtime log directory group-writable # Make the airtime log directory group-writable
loudCmd "chmod 775 /var/log/airtime" loudCmd "chmod 775 /var/log/airtime"
# Create the Celery user # Create the Celery user
if [ "$dist" = "centos" ]; then if $is_centos_dist; then
loudCmd "id celery || adduser --no-create-home -c 'LibreTime Celery' -r celery || true" loudCmd "id celery 2>/dev/null || adduser --no-create-home -c 'LibreTime Celery' -r celery || true"
loudCmd "systemctl enable airtime-celery"
else else
loudCmd "id celery || adduser --no-create-home --gecos 'LibreTime Celery' --disabled-login --firstuid 1 --lastuid 999 celery" loudCmd "id celery 2>/dev/null || adduser --no-create-home --gecos 'LibreTime Celery' --disabled-login --firstuid 1 --lastuid 999 celery"
loudCmd "update-rc.d airtime-celery defaults"
fi fi
# Add celery to the www-data group # Add celery to the www-data group
loudCmd "usermod -G ${web_user} -a celery" loudCmd "usermod -G ${web_user} -a celery"
# CentOS installs celery in /usr/bin which differs from other distros. Make
if [ "$dist" = "ubuntu" ] && [ "$code" != "xenial" ]; then # available in /usr/local/bin as systemd requires an absolute path.
loudCmd "initctl reload-configuration" [[ ! -e /usr/local/bin/celery ]] && ln -s /usr/bin/celery /usr/local/bin/celery
elif [ "$dist" = "ubuntu" ] && [ "$code" = "xenial" ]; then systemInitInstall airtime-celery
loudCmd "systemctl daemon-reload"
fi
verbose "...Done" verbose "...Done"
verbose "\n * Installing airtime_analyzer..." verbose "\n * Installing airtime_analyzer..."
loudCmd "python ${AIRTIMEROOT}/python_apps/airtime_analyzer/setup.py install --install-scripts=/usr/bin" loudCmd "python ${AIRTIMEROOT}/python_apps/airtime_analyzer/setup.py install --install-scripts=/usr/bin --no-init-script"
if [ "$dist" = "ubuntu" ] && [ "$code" != "xenial" ]; then systemInitInstall airtime_analyzer $web_user
loudCmd "initctl reload-configuration"
elif [ "$dist" = "ubuntu" ] && [ "$code" = "xenial" ]; then
loudCmd "systemctl daemon-reload"
fi
verbose "...Done" verbose "...Done"
for i in /etc/init/airtime*.template; do
chmod 644 $i
sed -i "s/WEB_USER/${web_user}/g" $i
mv $i ${i%.template}
done
set +e
if [ "$dist" = "ubuntu" ] && [ "$code" != "xenial" ] ; then
loudCmd "initctl reload-configuration"
elif [ "$dist" = "ubuntu" ] && [ "$code" = "xenial" ]; then
loudCmd "systemctl daemon-reload"
fi
# airtime-celery only has an init.d startup script
if [ "$dist" = "centos" ]; then
loudCmd "systemctl enable airtime-celery"
else
loudCmd "update-rc.d airtime-celery defaults" # Start at bootup, on Debian
fi
# On Ubuntu, we already have the upstart configs, so this is redundant
# and causes multiple processes to spawn on startup
if [ "$dist" = "debian" ]; then
loudCmd "systemctl daemon-reload" #systemd hipsters
loudCmd "update-rc.d airtime-playout defaults" # Start at bootup, on Debian
loudCmd "update-rc.d airtime-liquidsoap defaults" # Start at bootup, on Debian
loudCmd "update-rc.d airtime_analyzer defaults" # Start at bootup, on Debian
fi
if [ "$dist" = "centos" ]; then
loudCmd "systemctl enable airtime-playout"
loudCmd "systemctl enable airtime-liquidsoap"
loudCmd "systemctl enable airtime_analyzer"
fi
set -e
if [ ! -d /var/log/airtime ]; then if [ ! -d /var/log/airtime ]; then
loud "\n-----------------------------------------------------" loud "\n-----------------------------------------------------"
loud " * Installing Log Files * " loud " * Installing Log Files * "
@ -641,16 +933,25 @@ verbose "\n * Setting permissions on /var/tmp/airtime..."
chmod -R a+x /var/tmp/airtime chmod -R a+x /var/tmp/airtime
chown -R ${web_user}:${web_user} /var/tmp/airtime/ chown -R ${web_user}:${web_user} /var/tmp/airtime/
# PHP Config File for Apache loud "\n-----------------------------------------------------"
if [ ${dist,,} == "ubuntu" ] && [ ${code,,} == "xenial" ]; then loud " * Configuring PHP in Apache * "
libretime_phpini="/etc/php/7.0/apache2/conf.d/airtime.ini" loud "-----------------------------------------------------"
# Test common locations for php conf directory
php_conf_dirs=(
"/etc/php/7.0/apache2/conf.d" # Ubuntu Xenial
"/etc/php5/apache2/conf.d" # Debian Jessie, Ubuntu Trusty
"/etc/php.d" # CentOS 7
)
for php_conf in ${php_conf_dirs[@]}; do
[[ -d $php_conf ]] && break
done
if [[ -d $php_conf ]]; then
libretime_phpini="${php_conf}/airtime.ini"
else else
libretime_phpini="/etc/php5/apache2/conf.d/airtime.ini" echo -e "ERROR: PHP Apache configuration folder does not exist or is in an unknown location!" >&2
fi exit 1
if [ "$dist" = "centos" ]; then
libretime_phpini="/etc/php.d/airtime.ini"
fi fi
verbose "Detected php conf directory at: $php_conf"
if [ ! -f "${libretime_phpini}" ]; then if [ ! -f "${libretime_phpini}" ]; then
verbose "\n * Creating LibreTime PHP config for Apache..." verbose "\n * Creating LibreTime PHP config for Apache..."
cp ${SCRIPT_DIR}/installer/php/airtime.ini ${libretime_phpini} cp ${SCRIPT_DIR}/installer/php/airtime.ini ${libretime_phpini}
@ -659,24 +960,34 @@ else
fi fi
# Enable Apache modules # Enable Apache modules
if [ "$dist" != "centos" ] && [ "$code" != "xenial" ]; then if $is_ubuntu_xenial; then
loudCmd "a2enmod rewrite php7.0"
elif $is_centos_dist; then
verbose "TODO: enable Apache modules mod_rewrite and mod_php manually"
else
loudCmd "a2enmod rewrite php5" loudCmd "a2enmod rewrite php5"
elif [ "$dist" = "ubuntu" ] && [ "$code" = "xenial" ]; then
loudCmd "a2enmod rewrite"
loudCmd "a2enmod php7.0"
fi fi
loud "\n-----------------------------------------------------" loud "\n-----------------------------------------------------"
loud " * Configuring PostgreSQL * " loud " * Configuring PostgreSQL * "
loud "-----------------------------------------------------" loud "-----------------------------------------------------"
# Ensure postgres is running - It isn't after you install the postgres package on Ubuntu 15.04 # Ensure postgres is running - It isn't after you install the postgres package on Ubuntu 15.04
loudCmd "service postgresql start" systemInitCommand start postgresql
setupAirtimePostgresUser() { setupAirtimePostgresUser() {
# here-doc to execute this block as postgres user # here-doc to execute this block as postgres user
su postgres <<'EOF' su postgres <<'EOF'
set +e set +e
psql -d postgres -tAc "CREATE USER airtime WITH ENCRYPTED PASSWORD 'airtime'; ALTER USER airtime CREATEDB;" count=$(psql -d postgres -tAc "SELECT count(*) FROM pg_roles WHERE rolname='airtime';")
if [[ $count -eq 0 ]]; then
psql -d postgres -tAc "CREATE USER airtime WITH ENCRYPTED PASSWORD 'airtime'; ALTER USER airtime CREATEDB;"
[[ $? -eq 0 ]] &&
echo "Created airtime user in PostgreSQL" ||
echo "$0:${FUNCNAME}(): ERROR: Can't create airtime user in PostgreSQL!"
else
echo "airtime user already exists in PostgreSQL"
fi
set -e set -e
# don't indent this! # don't indent this!
EOF EOF
@ -751,19 +1062,23 @@ if [ "$ignore_dependencies" = "f" ]; then
loud " * Installing Locales * " loud " * Installing Locales * "
loud "-----------------------------------------------------" loud "-----------------------------------------------------"
set +e if $is_centos_dist; then
verbose "\n * Generating locales" loud "\n not required on $dist"
for i in `ls ${web_root}/../locale | grep ".._.."`; do else
if [ "$dist" = "debian" ]; then set +e
grep -qi "^$i" /etc/locale.gen verbose "\n * Generating locales"
if [ $? -ne 0 ]; then for i in `ls ${web_root}/../locale | grep ".._.."`; do
verbose "$i.UTF-8 UTF-8" >> /etc/locale.gen if [ "$dist" = "debian" ]; then
grep -qi "^$i" /etc/locale.gen
if [ $? -ne 0 ]; then
verbose "$i.UTF-8 UTF-8" >> /etc/locale.gen
fi
else
loudCmd "locale-gen \"$i.utf8\""
fi fi
else done
loudCmd "locale-gen \"$i.utf8\"" set -e
fi fi
done
set -e
if [ "$dist" = "debian" ]; then if [ "$dist" = "debian" ]; then
loudCmd "/usr/sbin/locale-gen" loudCmd "/usr/sbin/locale-gen"
@ -783,18 +1098,17 @@ if [ "$selinux" = "t" ]; then
fi fi
verbose "\n * Reloading apache..." verbose "\n * Reloading apache..."
if [ "$dist" != "centos" ]; then systemInitCommand restart ${apache_service}
loudCmd "service ${apache_bin} reload 2>/dev/null" # NOTE: ip command works on all supported platforms
verbose "...Done" if $is_centos_dist; then
IP=$(ifconfig eth0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://')
else
verbose "systemctl restart ${apache_bin} 2>/dev/null"
loudCmd "systemctl restart ${apache_bin} 2>/dev/null"
verbose "...Done"
IP=$(ip -o -4 address show dev eth0 | grep -Po 'inet \K[\d.]+') IP=$(ip -o -4 address show dev eth0 | grep -Po 'inet \K[\d.]+')
else
# not on centos
ip_device="eth0"
$is_ubuntu_xenial && ip_device="enp0s8"
IP=$(ifconfig ${ip_device} 2>/dev/null |awk -F'[ :]+' '/inet addr:/ {print $4}')
fi fi
verbose "...Done"
echo -e "\n-----------------------------------------------------" echo -e "\n-----------------------------------------------------"
echo " * Basic Setup DONE! * " echo " * Basic Setup DONE! * "

View File

@ -7,7 +7,7 @@ User=celery
Group=celery Group=celery
Environment=RMQ_CONFIG_FILE=/etc/airtime/airtime.conf Environment=RMQ_CONFIG_FILE=/etc/airtime/airtime.conf
WorkingDirectory=/srv/airtime WorkingDirectory=/srv/airtime
ExecStart=/bin/celery worker -A airtime-celery.tasks:celery --time-limit=300 --concurrency=1 --config=celeryconfig -l INFO ExecStart=/usr/local/bin/celery worker -A airtime-celery.tasks:celery --time-limit=300 --concurrency=1 --config=celeryconfig -l INFO
Restart=always Restart=always
[Install] [Install]

View File

@ -124,27 +124,6 @@ restorecon -Rv /vagrant /etc/airtime /srv/airtime
# Disable default apache page # Disable default apache page
sed -i -e 's/^/#/' /etc/httpd/conf.d/welcome.conf sed -i -e 's/^/#/' /etc/httpd/conf.d/welcome.conf
# Quick and dirty systemd unit install (will be in package later)
unit_dir="/etc/systemd/system"
unit_src_dir="/vagrant/installer/systemd"
cp -rp ${unit_src_dir}/*.service ${unit_dir}
# Overrides to use apache user for now (final packaging will have dedicated users)
for service in `ls ${unit_src_dir}/*.service`; do
unit_name=`basename ${service}`
if [ "$unit_name" = "airtime-celery.service" ]; then
continue
fi
sed -i \
-e 's/User=.*/User=apache/' \
-e 's/Group=.*/Group=apache/' \
${unit_dir}/${unit_name}
done
# for good measure, lets reload em
systemctl daemon-reload
# celery will not run unless we install a specific version (https://github.com/pypa/setuptools/issues/942) # celery will not run unless we install a specific version (https://github.com/pypa/setuptools/issues/942)
# this will need to be figured out later on and will get overriden by the docs installer anyhow :( # this will need to be figured out later on and will get overriden by the docs installer anyhow :(
pip install setuptools==33.1.1 pip install setuptools==33.1.1

View File

@ -0,0 +1,18 @@
description "LibreTime Celery Service"
author "help@libretime.org"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
setuid celery
setgid celery
env LANG='en_US.UTF-8'
env LC_ALL='en_US.UTF-8'
env RMQ_CONFIG_FILE=/etc/airtime/airtime.conf
chdir /srv/airtime
exec celery worker -A airtime-celery.tasks:celery --time-limit=300 --concurrency=1 --config=celeryconfig -l INFO