heat/bin/heat-keystone-setup
DennyZhang 88b8e20f1c add assertion to heat-keystone-setup script
Defensive check for various critical steps in the script

Change-Id: I9df01011940d80532787c3acaf0cc8ec10e97cc8
closes-bug: #1260561
2013-12-19 11:06:53 -06:00

321 lines
9.5 KiB
Bash
Executable File

#!/bin/bash
set +e
KEYSTONE_CONF=${KEYSTONE_CONF:-/etc/keystone/keystone.conf}
# Extract some info from Keystone's configuration file
if [[ -r "$KEYSTONE_CONF" ]]; then
CONFIG_SERVICE_TOKEN=$(sed 's/[[:space:]]//g' $KEYSTONE_CONF | grep ^admin_token= | cut -d'=' -f2)
CONFIG_ADMIN_PORT=$(sed 's/[[:space:]]//g' $KEYSTONE_CONF | grep ^admin_port= | cut -d'=' -f2)
fi
SERVICE_TOKEN=${SERVICE_TOKEN:-$CONFIG_SERVICE_TOKEN}
SERVICE_ENDPOINT=${SERVICE_ENDPOINT:-http://127.0.0.1:${CONFIG_ADMIN_PORT:-35357}/v2.0}
if [[ -z "$SERVICE_TOKEN" ]]; then
echo "No service token found." >&2
echo "Set SERVICE_TOKEN manually from keystone.conf admin_token." >&2
exit 1
fi
set_admin_token() {
alias keystone="keystone --token $SERVICE_TOKEN \
--endpoint $SERVICE_ENDPOINT"
}
unset_admin_token() {
unalias keystone
}
#### utilities functions merged from devstack to check required parameter is not empty
# Prints line number and "message" in error format
# err $LINENO "message"
function err() {
local exitcode=$?
errXTRACE=$(set +o | grep xtrace)
set +o xtrace
local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
echo $msg 1>&2;
if [[ -n ${SCREEN_LOGDIR} ]]; then
echo $msg >> "${SCREEN_LOGDIR}/error.log"
fi
$errXTRACE
return $exitcode
}
# Prints backtrace info
# filename:lineno:function
function backtrace {
local level=$1
local deep=$((${#BASH_SOURCE[@]} - 1))
echo "[Call Trace]"
while [ $level -le $deep ]; do
echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
deep=$((deep - 1))
done
}
# Prints line number and "message" then exits
# die $LINENO "message"
function die() {
local exitcode=$?
set +o xtrace
local line=$1; shift
if [ $exitcode == 0 ]; then
exitcode=1
fi
backtrace 2
err $line "$*"
exit $exitcode
}
# Checks an environment variable is not set or has length 0 OR if the
# exit code is non-zero and prints "message" and exits
# NOTE: env-var is the variable name without a '$'
# die_if_not_set $LINENO env-var "message"
function die_if_not_set() {
local exitcode=$?
FXTRACE=$(set +o | grep xtrace)
set +o xtrace
local line=$1; shift
local evar=$1; shift
if ! is_set $evar || [ $exitcode != 0 ]; then
die $line "$*"
fi
$FXTRACE
}
# Test if the named environment variable is set and not zero length
# is_set env-var
function is_set() {
local var=\$"$1"
eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
}
#######################################
get_data() {
local match_column=$(($1 + 1))
local regex="$2"
local output_column=$(($3 + 1))
shift 3
output=$("$@" | \
awk -F'|' \
"! /^\+/ && \$${match_column} ~ \"^ *${regex} *\$\" \
{ print \$${output_column} }")
die_if_not_set $LINENO output "Fail to get_data from '$@'"
echo "$output"
}
get_id () {
get_data 1 id 2 "$@"
}
get_column_num() {
local name=$1
shift
$@ | awk -F'|' "NR == 2 { for (i=2; i<NF; i++) if (\$i ~ \"^ *${name} *\$\") print (i - 1) }"
}
get_user() {
local username=$1
# Outut format of keystone user-list changed between essex and
# folsom - the columns have been re-ordered (!?), so detect what
# column to pass to get_data via get_column_num
namecol=$(get_column_num name keystone user-list)
die_if_not_set $LINENO namecol "Fail to get namecol for name by 'keystone user-list' "
local user_id=$(get_data $namecol $username 1 keystone user-list)
die_if_not_set $LINENO user_id "Fail to get user_id for $username by 'keystone user-list' "
if [ -n "$user_id" ]; then
echo "Found existing $username user" >&2
echo $user_id
else
echo "Creating $username user..." >&2
get_id keystone user-create --name=$username \
--pass="$SERVICE_PASSWORD" \
--tenant_id $SERVICE_TENANT \
--email=$username@example.com
fi
}
add_role() {
local user_id=$1
local tenant=$2
local role_id=$3
local username=$4
# The keystone argument format changed between essex and folsom
# so we use the fact that the folsom keystone version has a new
# option "user-role-list" to detect we're on that newer version
# This also allows us to detect when the user already has the
# requested role_id, preventing an error on folsom
user_roles=$(keystone user-role-list \
--user_id $user_id\
--tenant_id $tenant 2>/dev/null)
die_if_not_set $LINENO user_roles "Fail to get user_roles for tenant($tenant) and user_id($user_id)"
if [ $? == 0 ]; then
# Folsom
existing_role=$(get_data 1 $role_id 1 echo "$user_roles")
if [ -n "$existing_role" ]
then
echo "User $username already has role $role_id" >&2
return
fi
keystone user-role-add --tenant_id $tenant \
--user_id $user_id \
--role_id $role_id
else
# Essex
keystone user-role-add --tenant_id $tenant \
--user $user_id \
--role $role_id
fi
}
create_role() {
local role_name=$1
role_id=$(get_data 2 $role_name 1 keystone role-list)
if [ -n "$role_id" ]
then
echo "Role $role_name already exists : $role_id" >&2
else
keystone role-create --name $role_name
fi
}
get_endpoint() {
local service_type=$1
unset_admin_token
keystone endpoint-get --service $service_type
set_admin_token
}
delete_endpoint() {
local service_type=$1
case $service_type in
volume) urlsuffix='\\\\$\\\\(tenant_id)s';;
orchestration) urlsuffix='%[(]tenant_id[)]s';;
# cloudformation has no hash suffix
*) urlsuffix=''
esac
local url=$(get_data 1 "${service_type}[.]publicURL" 2 \
get_endpoint $service_type 2>/dev/null | \
sed -r "s/[a-f0-9]{32}/$urlsuffix/")
if [ -n "$url" ]; then
local endpoints=$(get_data 3 $url 1 keystone endpoint-list)
for endpoint in $endpoints; do
echo "Removing $service_type endpoint ${endpoint}..." >&2
keystone endpoint-delete "$endpoint" >&2
done
if [ -z "$endpoints" ]; then false; fi
else
false
fi
}
delete_all_endpoints() {
while delete_endpoint $1; do
true
done
}
delete_service() {
local service_type=$1
delete_all_endpoints $service_type
local service_ids=$(get_data 3 $service_type 1 keystone service-list)
for service in $service_ids; do
local service_name=$(get_data 1 $service 2 keystone service-list)
echo "Removing $service_name:$service_type service..." >&2
keystone service-delete $service >&2
done
}
get_service() {
local service_name=$1
local service_type=$2
local description="$3"
delete_service $service_type
get_id keystone service-create --name=$service_name \
--type=$service_type \
--description="$description"
}
add_endpoint() {
local service_id=$1
local url="$2"
keystone endpoint-create --region RegionOne --service_id $service_id \
--publicurl "$url" --adminurl "$url" --internalurl "$url" >&2
}
keystone_setup() {
TENANT_ID=$(get_data 1 tenant_id 2 keystone token-get)
die_if_not_set $LINENO TENANT_ID "Fail to get TENANT_ID by 'token-get' "
set_admin_token
ADMIN_ROLE=$(get_data 2 admin 1 keystone role-list)
die_if_not_set $LINENO TENANT_ID "Fail to get ADMIN_ROLE by 'keystone role-list' "
SERVICE_TENANT=$(get_data 2 service 1 keystone tenant-list)
die_if_not_set $LINENO SERVICE_TENANT "Fail to get service tenant 'keystone tenant-list' "
SERVICE_PASSWORD=${SERVICE_PASSWORD:-$OS_PASSWORD}
SERVICE_HOST=${SERVICE_HOST:-localhost}
if [[ "$SERVICE_PASSWORD" == "$OS_PASSWORD" ]]; then
echo "Using the OS_PASSWORD for the SERVICE_PASSWORD." >&2
fi
if [[ "$SERVICE_HOST" == "localhost" ]]; then
echo "Endpoints will be registered as localhost, but this usually won't work."
echo "Set SERVICE_HOST to a publically accessible hostname/IP instead."
fi
echo ADMIN_ROLE $ADMIN_ROLE
echo SERVICE_TENANT $SERVICE_TENANT
echo SERVICE_PASSWORD $SERVICE_PASSWORD
echo SERVICE_TOKEN $SERVICE_TOKEN
echo SERVICE_HOST $SERVICE_HOST
HEAT_USERNAME="heat"
HEAT_USERID=$(get_user $HEAT_USERNAME)
die_if_not_set $LINENO HEAT_USERID "Fail to get user for $HEAT_USERNAME"
echo HEAT_USERID $HEAT_USERID
add_role $HEAT_USERID $SERVICE_TENANT $ADMIN_ROLE $HEAT_USERNAME
# Create a special role which template-defined "stack users" are
# assigned to in the engine when they are created, this allows them
# to be more easily differentiated from other users (e.g so we can
# lock down these implicitly untrusted users via RBAC policy)
STACK_USER_ROLE="heat_stack_user"
create_role $STACK_USER_ROLE
HEAT_CFN_SERVICE=$(get_service heat-cfn cloudformation \
"Heat CloudFormation API")
add_endpoint $HEAT_CFN_SERVICE "http://$SERVICE_HOST:8000/v1"
HEAT_OS_SERVICE=$(get_service heat orchestration \
"Heat API")
add_endpoint $HEAT_OS_SERVICE "http://$SERVICE_HOST:8004/v1/%(tenant_id)s"
}
if [[ ${BASH_SOURCE[0]} == ${0} ]]; then
keystone_setup
fi