heat/devstack/lib/heat
Matthew Treinish 6b22300c8f Don't remove uwsgi config files on stop
Removing the uwsgi config files on stop breaks upgrades when using
uwsgi, so let's not do that. Keeping the file deletes in cleanup
makes sense and those calls remain.

Change-Id: I603754c3f5ed5d2f143cf789df96018ec99ad692
2017-09-02 19:00:25 -04:00

487 lines
18 KiB
Bash

#!/bin/bash
#
# lib/heat
# Install and start **Heat** service
# To enable, add the following to localrc
#
# ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng
# Dependencies:
# (none)
# stack.sh
# ---------
# - install_heatclient
# - install_heat
# - configure_heatclient
# - configure_heat
# - init_heat
# - start_heat
# - stop_heat
# - cleanup_heat
# Save trace setting
_XTRACE_HEAT=$(set +o | grep xtrace)
set +o xtrace
# Defaults
# --------
# set up default directories
GITDIR["python-heatclient"]=$DEST/python-heatclient
# heat service
HEAT_REPO=${HEAT_REPO:-${GIT_BASE}/openstack/heat.git}
HEAT_BRANCH=${HEAT_BRANCH:-master}
# python heat client library
GITREPO["python-heatclient"]=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git}
GITBRANCH["python-heatclient"]=${HEATCLIENT_BRANCH:-master}
# Use HEAT_USE_MOD_WSGI for backward compatibility
HEAT_USE_APACHE=${HEAT_USE_APACHE:-${HEAT_USE_MOD_WSGI:-True}}
HEAT_DIR=$DEST/heat
HEAT_FILES_DIR=$HEAT_DIR/heat/httpd/files
HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
HEAT_STANDALONE=$(trueorfalse False HEAT_STANDALONE)
HEAT_ENABLE_ADOPT_ABANDON=$(trueorfalse False HEAT_ENABLE_ADOPT_ABANDON)
HEAT_CONF_DIR=/etc/heat
HEAT_CONF=$HEAT_CONF_DIR/heat.conf
HEAT_ENV_DIR=$HEAT_CONF_DIR/environment.d
HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates
HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP}
HEAT_API_PORT=${HEAT_API_PORT:-8004}
HEAT_SERVICE_USER=${HEAT_SERVICE_USER:-heat}
HEAT_TRUSTEE_USER=${HEAT_TRUSTEE_USER:-$HEAT_SERVICE_USER}
HEAT_TRUSTEE_PASSWORD=${HEAT_TRUSTEE_PASSWORD:-$SERVICE_PASSWORD}
HEAT_TRUSTEE_DOMAIN=${HEAT_TRUSTEE_DOMAIN:-default}
# Support entry points installation of console scripts
HEAT_BIN_DIR=$(get_python_exec_prefix)
HEAT_API_UWSGI_CONF=$HEAT_CONF_DIR/heat-api-uwsgi.ini
HEAT_CFN_API_UWSGI_CONF=$HEAT_CONF_DIR/heat-api-cfn-uwsgi.ini
HEAT_CW_API_UWSGI_CONF=$HEAT_CONF_DIR/heat-api-cloudwatch-uwsgi.ini
HEAT_API_UWSGI=$HEAT_BIN_DIR/heat-wsgi-api
HEAT_CFN_API_UWSGI=$HEAT_BIN_DIR/heat-wsgi-api-cfn
HEAT_CW_API_UWSGI=$HEAT_BIN_DIR/heat-wsgi-api-cloudwatch
# other default options
if [[ "$HEAT_STANDALONE" == "True" ]]; then
# for standalone, use defaults which require no service user
HEAT_STACK_DOMAIN=$(trueorfalse False HEAT_STACK_DOMAIN)
HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-password}
if [[ ${HEAT_DEFERRED_AUTH} != "password" ]]; then
# Heat does not support keystone trusts when deployed in
# standalone mode
die $LINENO \
'HEAT_DEFERRED_AUTH can only be set to "password" when HEAT_STANDALONE is True.'
fi
else
HEAT_STACK_DOMAIN=$(trueorfalse True HEAT_STACK_DOMAIN)
HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-}
fi
HEAT_PLUGIN_DIR=${HEAT_PLUGIN_DIR:-$DATA_DIR/heat/plugins}
ENABLE_HEAT_PLUGINS=${ENABLE_HEAT_PLUGINS:-}
# Functions
# ---------
# Test if any Heat services are enabled
# is_heat_enabled
function is_heat_enabled {
[[ ,${ENABLED_SERVICES} =~ ,"h-" ]] && return 0
return 1
}
# cleanup_heat() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_heat {
if [[ "$HEAT_USE_APACHE" == "True" ]]; then
_cleanup_heat_apache_wsgi
fi
sudo rm -rf $HEAT_AUTH_CACHE_DIR
sudo rm -rf $HEAT_ENV_DIR
sudo rm -rf $HEAT_TEMPLATES_DIR
sudo rm -rf $HEAT_CONF_DIR
}
# configure_heat() - Set config files, create data dirs, etc
function configure_heat {
sudo install -d -o $STACK_USER $HEAT_CONF_DIR
# remove old config files
rm -f $HEAT_CONF_DIR/heat-*.conf
HEAT_API_CFN_HOST=${HEAT_API_CFN_HOST:-$HOST_IP}
HEAT_API_CFN_PORT=${HEAT_API_CFN_PORT:-8000}
HEAT_ENGINE_HOST=${HEAT_ENGINE_HOST:-$SERVICE_HOST}
HEAT_ENGINE_PORT=${HEAT_ENGINE_PORT:-8001}
HEAT_API_CW_HOST=${HEAT_API_CW_HOST:-$HOST_IP}
HEAT_API_CW_PORT=${HEAT_API_CW_PORT:-8003}
HEAT_API_PASTE_FILE=$HEAT_CONF_DIR/api-paste.ini
HEAT_POLICY_FILE=$HEAT_CONF_DIR/policy.json
cp $HEAT_DIR/etc/heat/api-paste.ini $HEAT_API_PASTE_FILE
cp $HEAT_DIR/etc/heat/policy.json $HEAT_POLICY_FILE
# common options
iniset_rpc_backend heat $HEAT_CONF
if [[ "$HEAT_USE_APACHE" == "True" && "$WSGI_MODE" == "uwsgi" ]]; then
iniset $HEAT_CONF DEFAULT heat_metadata_server_url http://$HEAT_API_CFN_HOST/heat-api-cfn
iniset $HEAT_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST/heat-api-cfn/v1/waitcondition
iniset $HEAT_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST/heat-api-cloudwatch
else
iniset $HEAT_CONF DEFAULT heat_metadata_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT
iniset $HEAT_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1/waitcondition
iniset $HEAT_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST:$HEAT_API_CW_PORT
fi
iniset $HEAT_CONF database connection `database_connection_url heat`
# we are using a hardcoded auth_encryption_key as it has to be the same for
# multinode deployment.
iniset $HEAT_CONF DEFAULT auth_encryption_key "767c3ed056cbaa3b9dfedb8c6f825bf0"
iniset $HEAT_CONF DEFAULT region_name_for_services "$REGION_NAME"
# logging
iniset $HEAT_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
local no_format="False"
if [[ "$HEAT_USE_APACHE" == "True" && "$WSGI_MODE" != "uwsgi" ]]; then
no_format="True"
fi
# Format logging
setup_logging $HEAT_CONF $no_format
if [[ ! -z "$HEAT_DEFERRED_AUTH" ]]; then
iniset $HEAT_CONF DEFAULT deferred_auth_method $HEAT_DEFERRED_AUTH
fi
if [[ "$HEAT_USE_APACHE" == "True" ]]; then
if [[ $WSGI_MODE == "uwsgi" ]]; then
write_uwsgi_config "$HEAT_API_UWSGI_CONF" "$HEAT_API_UWSGI" "/heat-api"
# configure threads for h-api to avoid IO wait and messaging timeout. We use
# 'nproc/4' to calculate API workers, hence, 4 would be probably correct
# approximation.
iniset "$HEAT_API_UWSGI_CONF" uwsgi threads 4
write_uwsgi_config "$HEAT_CFN_API_UWSGI_CONF" "$HEAT_CFN_API_UWSGI" "/heat-api-cfn"
write_uwsgi_config "$HEAT_CW_API_UWSGI_CONF" "$HEAT_CW_API_UWSGI" "/heat-api-cloudwatch"
else
_config_heat_apache_wsgi
fi
fi
if [[ "$HEAT_STANDALONE" = "True" ]]; then
iniset $HEAT_CONF paste_deploy flavor standalone
iniset $HEAT_CONF clients_heat url "http://$HEAT_API_HOST:$HEAT_API_PORT/v1/%(tenant_id)s"
else
configure_auth_token_middleware $HEAT_CONF heat $HEAT_AUTH_CACHE_DIR
fi
# If HEAT_DEFERRED_AUTH is unset or explicitly set to trusts, configure
# the section for the client plugin associated with the trustee
if [ -z "$HEAT_DEFERRED_AUTH" -o "trusts" == "$HEAT_DEFERRED_AUTH" ]; then
iniset $HEAT_CONF trustee auth_type password
iniset $HEAT_CONF trustee auth_url $KEYSTONE_AUTH_URI
iniset $HEAT_CONF trustee username $HEAT_TRUSTEE_USER
iniset $HEAT_CONF trustee password $HEAT_TRUSTEE_PASSWORD
iniset $HEAT_CONF trustee user_domain_id $HEAT_TRUSTEE_DOMAIN
fi
# clients_keystone
iniset $HEAT_CONF clients_keystone auth_uri $KEYSTONE_AUTH_URI
# OpenStack API
iniset $HEAT_CONF heat_api bind_port $HEAT_API_PORT
iniset $HEAT_CONF heat_api workers "$API_WORKERS"
# Cloudformation API
iniset $HEAT_CONF heat_api_cfn bind_port $HEAT_API_CFN_PORT
# Cloudwatch API
iniset $HEAT_CONF heat_api_cloudwatch bind_port $HEAT_API_CW_PORT
if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
iniset $HEAT_CONF clients_keystone ca_file $SSL_BUNDLE_FILE
fi
if is_ssl_enabled_service "nova" || is_service_enabled tls-proxy; then
iniset $HEAT_CONF clients_nova ca_file $SSL_BUNDLE_FILE
fi
if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then
iniset $HEAT_CONF clients_cinder ca_file $SSL_BUNDLE_FILE
fi
if [[ "$HEAT_ENABLE_ADOPT_ABANDON" = "True" ]]; then
iniset $HEAT_CONF DEFAULT enable_stack_adopt true
iniset $HEAT_CONF DEFAULT enable_stack_abandon true
fi
iniset $HEAT_CONF cache enabled "True"
iniset $HEAT_CONF cache backend "dogpile.cache.memory"
if ! is_service_enabled c-bak; then
iniset $HEAT_CONF volumes backups_enabled false
fi
sudo install -d -o $STACK_USER $HEAT_ENV_DIR $HEAT_TEMPLATES_DIR
# copy the default environment
cp $HEAT_DIR/etc/heat/environment.d/* $HEAT_ENV_DIR/
# copy the default templates
cp $HEAT_DIR/etc/heat/templates/* $HEAT_TEMPLATES_DIR/
# Enable heat plugins.
# NOTE(nic): The symlink nonsense is necessary because when
# plugins are installed in "developer mode", the final component
# of their target directory is always "resources", which confuses
# Heat's plugin loader into believing that all plugins are named
# "resources", and therefore are all the same plugin; so it
# will only load one of them. Linking them all to a common
# location with unique names avoids that type of collision,
# while still allowing the plugins to be edited in-tree.
local err_count=0
if [[ -n "$ENABLE_HEAT_PLUGINS" ]]; then
mkdir -p $HEAT_PLUGIN_DIR
# Clean up cruft from any previous runs
rm -f $HEAT_PLUGIN_DIR/*
iniset $HEAT_CONF DEFAULT plugin_dirs $HEAT_PLUGIN_DIR
fi
for heat_plugin in $ENABLE_HEAT_PLUGINS; do
if [[ -d $HEAT_DIR/contrib/$heat_plugin ]]; then
setup_package $HEAT_DIR/contrib/$heat_plugin -e
ln -s $HEAT_DIR/contrib/$heat_plugin/$heat_plugin/resources $HEAT_PLUGIN_DIR/$heat_plugin
else
: # clear retval on the test so that we can roll up errors
err $LINENO "Requested Heat plugin(${heat_plugin}) not found."
err_count=$(($err_count + 1))
fi
done
[ $err_count -eq 0 ] || die $LINENO "$err_count of the requested Heat plugins could not be installed."
}
# init_heat() - Initialize database
function init_heat {
# recreate db only if one of the db services is enabled
if is_service_enabled $DATABASE_BACKENDS; then
# (re)create heat database
recreate_database heat
$HEAT_BIN_DIR/heat-manage db_sync
fi
create_heat_cache_dir
}
# create_heat_cache_dir() - Part of the init_heat() process
function create_heat_cache_dir {
# Create cache dirs
sudo install -d -o $STACK_USER $HEAT_AUTH_CACHE_DIR
}
# install_heatclient() - Collect source and prepare
function install_heatclient {
if use_library_from_git "python-heatclient"; then
git_clone_by_name "python-heatclient"
setup_dev_lib "python-heatclient"
sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-heatclient"]}/tools/,/etc/bash_completion.d/}heat.bash_completion
fi
}
# install_heat() - Collect source and prepare
function install_heat {
git_clone $HEAT_REPO $HEAT_DIR $HEAT_BRANCH
setup_develop $HEAT_DIR
if [[ "$HEAT_USE_APACHE" == "True" ]]; then
if [ "$WSGI_MODE" == "uwsgi" ]; then
pip_install uwsgi
else
install_apache_wsgi
fi
fi
}
# start_heat() - Start running processes, including screen
function start_heat {
run_process h-eng "$HEAT_BIN_DIR/heat-engine --config-file=$HEAT_CONF"
# If the site is not enabled then we are in a grenade scenario
local enabled_site_file
enabled_site_file=$(apache_site_config_for heat-api)
if [[ "$HEAT_USE_APACHE" == "True" ]]; then
if [[ -f ${enabled_site_file} && "$WSGI_MODE" != "uwsgi" ]]; then
enable_apache_site heat-api
enable_apache_site heat-api-cfn
enable_apache_site heat-api-cloudwatch
restart_apache_server
tail_log heat-api /var/log/$APACHE_NAME/heat_api.log
tail_log heat-api-access /var/log/$APACHE_NAME/heat_api_access.log
tail_log heat-api-cfn /var/log/$APACHE_NAME/heat_api_cfn.log
tail_log heat-api-cfn-access /var/log/$APACHE_NAME/heat_api_cfn_access.log
tail_log heat-api-cloudwatch /var/log/$APACHE_NAME/heat_api_cloudwatch.log
tail_log heat-api-cloudwatch-access /var/log/$APACHE_NAME/heat_api_cloudwatch_access.log
else
run_process h-api "$HEAT_BIN_DIR/uwsgi --ini $HEAT_API_UWSGI_CONF" ""
run_process h-api-cfn "$HEAT_BIN_DIR/uwsgi --ini $HEAT_CFN_API_UWSGI_CONF" ""
run_process h-api-cw "$HEAT_BIN_DIR/uwsgi --ini $HEAT_CW_API_UWSGI_CONF" ""
fi
else
run_process h-api "$HEAT_BIN_DIR/heat-api --config-file=$HEAT_CONF"
run_process h-api-cfn "$HEAT_BIN_DIR/heat-api-cfn --config-file=$HEAT_CONF"
run_process h-api-cw "$HEAT_BIN_DIR/heat-api-cloudwatch --config-file=$HEAT_CONF"
fi
}
function _stop_processes {
local serv
for serv in h-api h-api-cfn h-api-cw; do
stop_process $serv
done
}
# stop_heat() - Stop running processes
function stop_heat {
# Kill the screen windows
stop_process h-eng
if [[ "$HEAT_USE_APACHE" == "True" ]]; then
if [[ "$WSGI_MODE" == "uwsgi" ]]; then
_stop_processes
else
disable_apache_site heat-api
disable_apache_site heat-api-cfn
disable_apache_site heat-api-cloudwatch
restart_apache_server
fi
else
_stop_processes
fi
}
# _cleanup_heat_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
function _cleanup_heat_apache_wsgi {
if [[ "$WSGI_MODE" == "uwsgi" ]]; then
remove_uwsgi_config "$HEAT_API_UWSGI_CONF" "$HEAT_API_UWSGI"
remove_uwsgi_config "$HEAT_CFN_API_UWSGI_CONF" "$HEAT_CFN_API_UWSGI"
remove_uwsgi_config "$HEAT_CW_API_UWSGI_CONF" "$HEAT_CW_API_UWSGI"
fi
sudo rm -f $(apache_site_config_for heat-api)
sudo rm -f $(apache_site_config_for heat-api-cfn)
sudo rm -f $(apache_site_config_for heat-api-cloudwatch)
}
# _config_heat_apache_wsgi() - Set WSGI config files of Heat
function _config_heat_apache_wsgi {
local heat_apache_conf
heat_apache_conf=$(apache_site_config_for heat-api)
local heat_cfn_apache_conf
heat_cfn_apache_conf=$(apache_site_config_for heat-api-cfn)
local heat_cloudwatch_apache_conf
heat_cloudwatch_apache_conf=$(apache_site_config_for heat-api-cloudwatch)
local heat_ssl=""
local heat_certfile=""
local heat_keyfile=""
local heat_api_port=$HEAT_API_PORT
local heat_cfn_api_port=$HEAT_API_CFN_PORT
local heat_cw_api_port=$HEAT_API_CW_PORT
local venv_path=""
sudo cp $HEAT_FILES_DIR/heat-api.conf $heat_apache_conf
sudo sed -e "
s|%PUBLICPORT%|$heat_api_port|g;
s|%APACHE_NAME%|$APACHE_NAME|g;
s|%HEAT_BIN_DIR%|$HEAT_BIN_DIR|g;
s|%API_WORKERS%|$API_WORKERS|g;
s|%SSLENGINE%|$heat_ssl|g;
s|%SSLCERTFILE%|$heat_certfile|g;
s|%SSLKEYFILE%|$heat_keyfile|g;
s|%USER%|$STACK_USER|g;
s|%VIRTUALENV%|$venv_path|g
" -i $heat_apache_conf
sudo cp $HEAT_FILES_DIR/heat-api-cfn.conf $heat_cfn_apache_conf
sudo sed -e "
s|%PUBLICPORT%|$heat_cfn_api_port|g;
s|%APACHE_NAME%|$APACHE_NAME|g;
s|%HEAT_BIN_DIR%|$HEAT_BIN_DIR|g;
s|%API_WORKERS%|$API_WORKERS|g;
s|%SSLENGINE%|$heat_ssl|g;
s|%SSLCERTFILE%|$heat_certfile|g;
s|%SSLKEYFILE%|$heat_keyfile|g;
s|%USER%|$STACK_USER|g;
s|%VIRTUALENV%|$venv_path|g
" -i $heat_cfn_apache_conf
sudo cp $HEAT_FILES_DIR/heat-api-cloudwatch.conf $heat_cloudwatch_apache_conf
sudo sed -e "
s|%PUBLICPORT%|$heat_cw_api_port|g;
s|%APACHE_NAME%|$APACHE_NAME|g;
s|%HEAT_BIN_DIR%|$HEAT_BIN_DIR|g;
s|%API_WORKERS%|$API_WORKERS|g;
s|%SSLENGINE%|$heat_ssl|g;
s|%SSLCERTFILE%|$heat_certfile|g;
s|%SSLKEYFILE%|$heat_keyfile|g;
s|%USER%|$STACK_USER|g;
s|%VIRTUALENV%|$venv_path|g
" -i $heat_cloudwatch_apache_conf
}
# create_heat_accounts() - Set up common required heat accounts
function create_heat_accounts {
if [[ "$HEAT_STANDALONE" != "True" ]]; then
local heat_api_service_url
local heat_cfn_api_service_url
if [[ "$HEAT_USE_APACHE" == "True" && "$WSGI_MODE" == "uwsgi" ]]; then
heat_api_service_url="$SERVICE_PROTOCOL://$HEAT_API_HOST/heat-api/v1/\$(project_id)s"
heat_cfn_api_service_url="$SERVICE_PROTOCOL://$HEAT_API_CFN_HOST/heat-api-cfn/v1"
else
heat_api_service_url="$SERVICE_PROTOCOL://$HEAT_API_HOST:$HEAT_API_PORT/v1/\$(project_id)s"
heat_cfn_api_service_url="$SERVICE_PROTOCOL://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1"
fi
create_service_user "heat" "admin"
get_or_create_service "heat" "orchestration" "Heat Orchestration Service"
get_or_create_endpoint \
"orchestration" \
"$REGION_NAME" \
"$heat_api_service_url" "$heat_api_service_url" "$heat_api_service_url"
get_or_create_service "heat-cfn" "cloudformation" "Heat CloudFormation Service"
get_or_create_endpoint \
"cloudformation" \
"$REGION_NAME" \
"$heat_cfn_api_service_url" "$heat_cfn_api_service_url" "$heat_cfn_api_service_url"
# heat_stack_user role is for users created by Heat
get_or_create_role "heat_stack_user"
fi
if [[ "$HEAT_STACK_DOMAIN" == "True" ]]; then
# domain -> heat and user -> heat_domain_admin
domain_id=$(get_or_create_domain heat 'Owns users and projects created by heat')
iniset $HEAT_CONF DEFAULT stack_user_domain_id ${domain_id}
get_or_create_user heat_domain_admin $SERVICE_PASSWORD heat
get_or_add_user_domain_role admin heat_domain_admin heat
iniset $HEAT_CONF DEFAULT stack_domain_admin heat_domain_admin
iniset $HEAT_CONF DEFAULT stack_domain_admin_password $SERVICE_PASSWORD
fi
}
# Restore xtrace
$_XTRACE_HEAT
# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End: