782 lines
25 KiB
Bash
782 lines
25 KiB
Bash
#!/bin/bash -e
|
|
|
|
# Common utility functions used across all OpenStack charms.
|
|
|
|
error_out() {
|
|
juju-log "$CHARM ERROR: $@"
|
|
exit 1
|
|
}
|
|
|
|
function service_ctl_status {
|
|
# Return 0 if a service is running, 1 otherwise.
|
|
local svc="$1"
|
|
local status=$(service $svc status | cut -d/ -f1 | awk '{ print $2 }')
|
|
case $status in
|
|
"start") return 0 ;;
|
|
"stop") return 1 ;;
|
|
*) error_out "Unexpected status of service $svc: $status" ;;
|
|
esac
|
|
}
|
|
|
|
function service_ctl {
|
|
# control a specific service, or all (as defined by $SERVICES)
|
|
# service restarts will only occur depending on global $CONFIG_CHANGED,
|
|
# which should be updated in charm's set_or_update().
|
|
local config_changed=${CONFIG_CHANGED:-True}
|
|
if [[ $1 == "all" ]] ; then
|
|
ctl="$SERVICES"
|
|
else
|
|
ctl="$1"
|
|
fi
|
|
action="$2"
|
|
if [[ -z "$ctl" ]] || [[ -z "$action" ]] ; then
|
|
error_out "ERROR service_ctl: Not enough arguments"
|
|
fi
|
|
|
|
for i in $ctl ; do
|
|
case $action in
|
|
"start")
|
|
service_ctl_status $i || service $i start ;;
|
|
"stop")
|
|
service_ctl_status $i && service $i stop || return 0 ;;
|
|
"restart")
|
|
if [[ "$config_changed" == "True" ]] ; then
|
|
service_ctl_status $i && service $i restart || service $i start
|
|
fi
|
|
;;
|
|
esac
|
|
if [[ $? != 0 ]] ; then
|
|
juju-log "$CHARM: service_ctl ERROR - Service $i failed to $action"
|
|
fi
|
|
done
|
|
# all configs should have been reloaded on restart of all services, reset
|
|
# flag if its being used.
|
|
if [[ "$action" == "restart" ]] && [[ -n "$CONFIG_CHANGED" ]] &&
|
|
[[ "$ctl" == "all" ]]; then
|
|
CONFIG_CHANGED="False"
|
|
fi
|
|
}
|
|
|
|
function configure_install_source {
|
|
# Setup and configure installation source based on a config flag.
|
|
local src="$1"
|
|
|
|
# Default to installing from the main Ubuntu archive.
|
|
[[ $src == "distro" ]] || [[ -z "$src" ]] && return 0
|
|
|
|
. /etc/lsb-release
|
|
|
|
# standard 'ppa:someppa/name' format.
|
|
if [[ "${src:0:4}" == "ppa:" ]] ; then
|
|
juju-log "$CHARM: Configuring installation from custom src ($src)"
|
|
add-apt-repository -y "$src" || error_out "Could not configure PPA access."
|
|
return 0
|
|
fi
|
|
|
|
# standard 'deb http://url/ubuntu main' entries. gpg key ids must
|
|
# be appended to the end of url after a |, ie:
|
|
# 'deb http://url/ubuntu main|$GPGKEYID'
|
|
if [[ "${src:0:3}" == "deb" ]] ; then
|
|
juju-log "$CHARM: Configuring installation from custom src URL ($src)"
|
|
if echo "$src" | grep -q "|" ; then
|
|
# gpg key id tagged to end of url folloed by a |
|
|
url=$(echo $src | cut -d'|' -f1)
|
|
key=$(echo $src | cut -d'|' -f2)
|
|
juju-log "$CHARM: Importing repository key: $key"
|
|
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$key" || \
|
|
juju-log "$CHARM WARN: Could not import key from keyserver: $key"
|
|
else
|
|
juju-log "$CHARM No repository key specified."
|
|
url="$src"
|
|
fi
|
|
echo "$url" > /etc/apt/sources.list.d/juju_deb.list
|
|
return 0
|
|
fi
|
|
|
|
# Cloud Archive
|
|
if [[ "${src:0:6}" == "cloud:" ]] ; then
|
|
|
|
# current os releases supported by the UCA.
|
|
local cloud_archive_versions="folsom grizzly"
|
|
|
|
local ca_rel=$(echo $src | cut -d: -f2)
|
|
local u_rel=$(echo $ca_rel | cut -d- -f1)
|
|
local os_rel=$(echo $ca_rel | cut -d- -f2 | cut -d/ -f1)
|
|
|
|
[[ "$u_rel" != "$DISTRIB_CODENAME" ]] &&
|
|
error_out "Cannot install from Cloud Archive pocket $src " \
|
|
"on this Ubuntu version ($DISTRIB_CODENAME)!"
|
|
|
|
valid_release=""
|
|
for rel in $cloud_archive_versions ; do
|
|
if [[ "$os_rel" == "$rel" ]] ; then
|
|
valid_release=1
|
|
juju-log "Installing OpenStack ($os_rel) from the Ubuntu Cloud Archive."
|
|
fi
|
|
done
|
|
if [[ -z "$valid_release" ]] ; then
|
|
error_out "OpenStack release ($os_rel) not supported by "\
|
|
"the Ubuntu Cloud Archive."
|
|
fi
|
|
|
|
# CA staging repos are standard PPAs.
|
|
if echo $ca_rel | grep -q "staging" ; then
|
|
add-apt-repository -y ppa:ubuntu-cloud-archive/${os_rel}-staging
|
|
return 0
|
|
fi
|
|
|
|
# the others are LP-external deb repos.
|
|
case "$ca_rel" in
|
|
"$u_rel-$os_rel"|"$u_rel-$os_rel/updates") pocket="$u_rel-updates/$os_rel" ;;
|
|
"$u_rel-$os_rel/proposed") pocket="$u_rel-proposed/$os_rel" ;;
|
|
"$u_rel-$os_rel"|"$os_rel/updates") pocket="$u_rel-updates/$os_rel" ;;
|
|
"$u_rel-$os_rel/proposed") pocket="$u_rel-proposed/$os_rel" ;;
|
|
*) error_out "Invalid Cloud Archive repo specified: $src"
|
|
esac
|
|
|
|
apt-get -y install ubuntu-cloud-keyring
|
|
entry="deb http://ubuntu-cloud.archive.canonical.com/ubuntu $pocket main"
|
|
echo "$entry" \
|
|
>/etc/apt/sources.list.d/ubuntu-cloud-archive-$DISTRIB_CODENAME.list
|
|
return 0
|
|
fi
|
|
|
|
error_out "Invalid installation source specified in config: $src"
|
|
|
|
}
|
|
|
|
get_os_codename_install_source() {
|
|
# derive the openstack release provided by a supported installation source.
|
|
local rel="$1"
|
|
local codename="unknown"
|
|
. /etc/lsb-release
|
|
|
|
# map ubuntu releases to the openstack version shipped with it.
|
|
if [[ "$rel" == "distro" ]] ; then
|
|
case "$DISTRIB_CODENAME" in
|
|
"oneiric") codename="diablo" ;;
|
|
"precise") codename="essex" ;;
|
|
"quantal") codename="folsom" ;;
|
|
"raring") codename="grizzly" ;;
|
|
esac
|
|
fi
|
|
|
|
# derive version from cloud archive strings.
|
|
if [[ "${rel:0:6}" == "cloud:" ]] ; then
|
|
rel=$(echo $rel | cut -d: -f2)
|
|
local u_rel=$(echo $rel | cut -d- -f1)
|
|
local ca_rel=$(echo $rel | cut -d- -f2)
|
|
if [[ "$u_rel" == "$DISTRIB_CODENAME" ]] ; then
|
|
case "$ca_rel" in
|
|
"folsom"|"folsom/updates"|"folsom/proposed"|"folsom/staging")
|
|
codename="folsom" ;;
|
|
"grizzly"|"grizzly/updates"|"grizzly/proposed"|"grizzly/staging")
|
|
codename="grizzly" ;;
|
|
esac
|
|
fi
|
|
fi
|
|
|
|
# have a guess based on the deb string provided
|
|
if [[ "${rel:0:3}" == "deb" ]] || \
|
|
[[ "${rel:0:3}" == "ppa" ]] ; then
|
|
CODENAMES="diablo essex folsom grizzly havana"
|
|
for cname in $CODENAMES; do
|
|
if echo $rel | grep -q $cname; then
|
|
codename=$cname
|
|
fi
|
|
done
|
|
fi
|
|
echo $codename
|
|
}
|
|
|
|
get_os_codename_package() {
|
|
local pkg_vers=$(dpkg -l | grep "$1" | awk '{ print $3 }') || echo "none"
|
|
pkg_vers=$(echo $pkg_vers | cut -d: -f2) # epochs
|
|
case "${pkg_vers:0:6}" in
|
|
"2011.2") echo "diablo" ;;
|
|
"2012.1") echo "essex" ;;
|
|
"2012.2") echo "folsom" ;;
|
|
"2013.1") echo "grizzly" ;;
|
|
"2013.2") echo "havana" ;;
|
|
esac
|
|
}
|
|
|
|
get_os_version_codename() {
|
|
case "$1" in
|
|
"diablo") echo "2011.2" ;;
|
|
"essex") echo "2012.1" ;;
|
|
"folsom") echo "2012.2" ;;
|
|
"grizzly") echo "2013.1" ;;
|
|
"havana") echo "2013.2" ;;
|
|
esac
|
|
}
|
|
|
|
get_ip() {
|
|
dpkg -l | grep -q python-dnspython || {
|
|
apt-get -y install python-dnspython 2>&1 > /dev/null
|
|
}
|
|
hostname=$1
|
|
python -c "
|
|
import dns.resolver
|
|
import socket
|
|
try:
|
|
# Test to see if already an IPv4 address
|
|
socket.inet_aton('$hostname')
|
|
print '$hostname'
|
|
except socket.error:
|
|
try:
|
|
answers = dns.resolver.query('$hostname', 'A')
|
|
if answers:
|
|
print answers[0].address
|
|
except dns.resolver.NXDOMAIN:
|
|
pass
|
|
"
|
|
}
|
|
|
|
# Common storage routines used by cinder, nova-volume and swift-storage.
|
|
clean_storage() {
|
|
# if configured to overwrite existing storage, we unmount the block-dev
|
|
# if mounted and clear any previous pv signatures
|
|
local block_dev="$1"
|
|
juju-log "Cleaining storage '$block_dev'"
|
|
if grep -q "^$block_dev" /proc/mounts ; then
|
|
mp=$(grep "^$block_dev" /proc/mounts | awk '{ print $2 }')
|
|
juju-log "Unmounting $block_dev from $mp"
|
|
umount "$mp" || error_out "ERROR: Could not unmount storage from $mp"
|
|
fi
|
|
if pvdisplay "$block_dev" >/dev/null 2>&1 ; then
|
|
juju-log "Removing existing LVM PV signatures from $block_dev"
|
|
|
|
# deactivate any volgroups that may be built on this dev
|
|
vg=$(pvdisplay $block_dev | grep "VG Name" | awk '{ print $3 }')
|
|
if [[ -n "$vg" ]] ; then
|
|
juju-log "Deactivating existing volume group: $vg"
|
|
vgchange -an "$vg" ||
|
|
error_out "ERROR: Could not deactivate volgroup $vg. Is it in use?"
|
|
fi
|
|
echo "yes" | pvremove -ff "$block_dev" ||
|
|
error_out "Could not pvremove $block_dev"
|
|
else
|
|
juju-log "Zapping disk of all GPT and MBR structures"
|
|
sgdisk --zap-all $block_dev ||
|
|
error_out "Unable to zap $block_dev"
|
|
fi
|
|
}
|
|
|
|
function get_block_device() {
|
|
# given a string, return full path to the block device for that
|
|
# if input is not a block device, find a loopback device
|
|
local input="$1"
|
|
|
|
case "$input" in
|
|
/dev/*) [[ ! -b "$input" ]] && error_out "$input does not exist."
|
|
echo "$input"; return 0;;
|
|
/*) :;;
|
|
*) [[ ! -b "/dev/$input" ]] && error_out "/dev/$input does not exist."
|
|
echo "/dev/$input"; return 0;;
|
|
esac
|
|
|
|
# this represents a file
|
|
# support "/path/to/file|5G"
|
|
local fpath size oifs="$IFS"
|
|
if [ "${input#*|}" != "${input}" ]; then
|
|
size=${input##*|}
|
|
fpath=${input%|*}
|
|
else
|
|
fpath=${input}
|
|
size=5G
|
|
fi
|
|
|
|
## loop devices are not namespaced. This is bad for containers.
|
|
## it means that the output of 'losetup' may have the given $fpath
|
|
## in it, but that may not represent this containers $fpath, but
|
|
## another containers. To address that, we really need to
|
|
## allow some uniq container-id to be expanded within path.
|
|
## TODO: find a unique container-id that will be consistent for
|
|
## this container throughout its lifetime and expand it
|
|
## in the fpath.
|
|
# fpath=${fpath//%{id}/$THAT_ID}
|
|
|
|
local found=""
|
|
# parse through 'losetup -a' output, looking for this file
|
|
# output is expected to look like:
|
|
# /dev/loop0: [0807]:961814 (/tmp/my.img)
|
|
found=$(losetup -a |
|
|
awk 'BEGIN { found=0; }
|
|
$3 == f { sub(/:$/,"",$1); print $1; found=found+1; }
|
|
END { if( found == 0 || found == 1 ) { exit(0); }; exit(1); }' \
|
|
f="($fpath)")
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "multiple devices found for $fpath: $found" 1>&2
|
|
return 1;
|
|
fi
|
|
|
|
[ -n "$found" -a -b "$found" ] && { echo "$found"; return 1; }
|
|
|
|
if [ -n "$found" ]; then
|
|
echo "confused, $found is not a block device for $fpath";
|
|
return 1;
|
|
fi
|
|
|
|
# no existing device was found, create one
|
|
mkdir -p "${fpath%/*}"
|
|
truncate --size "$size" "$fpath" ||
|
|
{ echo "failed to create $fpath of size $size"; return 1; }
|
|
|
|
found=$(losetup --find --show "$fpath") ||
|
|
{ echo "failed to setup loop device for $fpath" 1>&2; return 1; }
|
|
|
|
echo "$found"
|
|
return 0
|
|
}
|
|
|
|
HAPROXY_CFG=/etc/haproxy/haproxy.cfg
|
|
HAPROXY_DEFAULT=/etc/default/haproxy
|
|
##########################################################################
|
|
# Description: Configures HAProxy services for Openstack API's
|
|
# Parameters:
|
|
# Space delimited list of service:port:mode combinations for which
|
|
# haproxy service configuration should be generated for. The function
|
|
# assumes the name of the peer relation is 'cluster' and that every
|
|
# service unit in the peer relation is running the same services.
|
|
#
|
|
# Services that do not specify :mode in parameter will default to http.
|
|
#
|
|
# Example
|
|
# configure_haproxy cinder_api:8776:8756:tcp nova_api:8774:8764:http
|
|
##########################################################################
|
|
configure_haproxy() {
|
|
local address=`unit-get private-address`
|
|
local name=${JUJU_UNIT_NAME////-}
|
|
cat > $HAPROXY_CFG << EOF
|
|
global
|
|
log 127.0.0.1 local0
|
|
log 127.0.0.1 local1 notice
|
|
maxconn 20000
|
|
user haproxy
|
|
group haproxy
|
|
spread-checks 0
|
|
|
|
defaults
|
|
log global
|
|
mode http
|
|
option httplog
|
|
option dontlognull
|
|
retries 3
|
|
timeout queue 1000
|
|
timeout connect 1000
|
|
timeout client 30000
|
|
timeout server 30000
|
|
|
|
listen stats :8888
|
|
mode http
|
|
stats enable
|
|
stats hide-version
|
|
stats realm Haproxy\ Statistics
|
|
stats uri /
|
|
stats auth admin:password
|
|
|
|
EOF
|
|
for service in $@; do
|
|
local service_name=$(echo $service | cut -d : -f 1)
|
|
local haproxy_listen_port=$(echo $service | cut -d : -f 2)
|
|
local api_listen_port=$(echo $service | cut -d : -f 3)
|
|
local mode=$(echo $service | cut -d : -f 4)
|
|
[[ -z "$mode" ]] && mode="http"
|
|
juju-log "Adding haproxy configuration entry for $service "\
|
|
"($haproxy_listen_port -> $api_listen_port)"
|
|
cat >> $HAPROXY_CFG << EOF
|
|
listen $service_name 0.0.0.0:$haproxy_listen_port
|
|
balance roundrobin
|
|
mode $mode
|
|
option ${mode}log
|
|
server $name $address:$api_listen_port check
|
|
EOF
|
|
local r_id=""
|
|
local unit=""
|
|
for r_id in `relation-ids cluster`; do
|
|
for unit in `relation-list -r $r_id`; do
|
|
local unit_name=${unit////-}
|
|
local unit_address=`relation-get -r $r_id private-address $unit`
|
|
if [ -n "$unit_address" ]; then
|
|
echo " server $unit_name $unit_address:$api_listen_port check" \
|
|
>> $HAPROXY_CFG
|
|
fi
|
|
done
|
|
done
|
|
done
|
|
echo "ENABLED=1" > $HAPROXY_DEFAULT
|
|
service haproxy restart
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Query HA interface to determine is cluster is configured
|
|
# Returns: 0 if configured, 1 if not configured
|
|
##########################################################################
|
|
is_clustered() {
|
|
local r_id=""
|
|
local unit=""
|
|
for r_id in $(relation-ids ha); do
|
|
if [ -n "$r_id" ]; then
|
|
for unit in $(relation-list -r $r_id); do
|
|
clustered=$(relation-get -r $r_id clustered $unit)
|
|
if [ -n "$clustered" ]; then
|
|
juju-log "Unit is haclustered"
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
juju-log "Unit is not haclustered"
|
|
return 1
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Return a list of all peers in cluster relations
|
|
##########################################################################
|
|
peer_units() {
|
|
local peers=""
|
|
local r_id=""
|
|
for r_id in $(relation-ids cluster); do
|
|
peers="$peers $(relation-list -r $r_id)"
|
|
done
|
|
echo $peers
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determines whether the current unit is the oldest of all
|
|
# its peers - supports partial leader election
|
|
# Returns: 0 if oldest, 1 if not
|
|
##########################################################################
|
|
oldest_peer() {
|
|
peers=$1
|
|
local l_unit_no=$(echo $JUJU_UNIT_NAME | cut -d / -f 2)
|
|
for peer in $peers; do
|
|
echo "Comparing $JUJU_UNIT_NAME with peers: $peers"
|
|
local r_unit_no=$(echo $peer | cut -d / -f 2)
|
|
if (($r_unit_no<$l_unit_no)); then
|
|
juju-log "Not oldest peer; deferring"
|
|
return 1
|
|
fi
|
|
done
|
|
juju-log "Oldest peer; might take charge?"
|
|
return 0
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determines whether the current service units is the
|
|
# leader within a) a cluster of its peers or b) across a
|
|
# set of unclustered peers.
|
|
# Parameters: CRM resource to check ownership of if clustered
|
|
# Returns: 0 if leader, 1 if not
|
|
##########################################################################
|
|
eligible_leader() {
|
|
if is_clustered; then
|
|
if ! is_leader $1; then
|
|
juju-log 'Deferring action to CRM leader'
|
|
return 1
|
|
fi
|
|
else
|
|
peers=$(peer_units)
|
|
if [ -n "$peers" ] && ! oldest_peer "$peers"; then
|
|
juju-log 'Deferring action to oldest service unit.'
|
|
return 1
|
|
fi
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Query Cluster peer interface to see if peered
|
|
# Returns: 0 if peered, 1 if not peered
|
|
##########################################################################
|
|
is_peered() {
|
|
local r_id=$(relation-ids cluster)
|
|
if [ -n "$r_id" ]; then
|
|
if [ -n "$(relation-list -r $r_id)" ]; then
|
|
juju-log "Unit peered"
|
|
return 0
|
|
fi
|
|
fi
|
|
juju-log "Unit not peered"
|
|
return 1
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determines whether host is owner of clustered services
|
|
# Parameters: Name of CRM resource to check ownership of
|
|
# Returns: 0 if leader, 1 if not leader
|
|
##########################################################################
|
|
is_leader() {
|
|
hostname=`hostname`
|
|
if [ -x /usr/sbin/crm ]; then
|
|
if crm resource show $1 | grep -q $hostname; then
|
|
juju-log "$hostname is cluster leader."
|
|
return 0
|
|
fi
|
|
fi
|
|
juju-log "$hostname is not cluster leader."
|
|
return 1
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determines whether enough data has been provided in
|
|
# configuration or relation data to configure HTTPS.
|
|
# Parameters: None
|
|
# Returns: 0 if HTTPS can be configured, 1 if not.
|
|
##########################################################################
|
|
https() {
|
|
local r_id=""
|
|
if [[ -n "$(config-get ssl_cert)" ]] &&
|
|
[[ -n "$(config-get ssl_key)" ]] ; then
|
|
return 0
|
|
fi
|
|
for r_id in $(relation-ids identity-service) ; do
|
|
for unit in $(relation-list -r $r_id) ; do
|
|
if [[ "$(relation-get -r $r_id https_keystone $unit)" == "True" ]] &&
|
|
[[ -n "$(relation-get -r $r_id ssl_cert $unit)" ]] &&
|
|
[[ -n "$(relation-get -r $r_id ssl_key $unit)" ]] &&
|
|
[[ -n "$(relation-get -r $r_id ca_cert $unit)" ]] ; then
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: For a given number of port mappings, configures apache2
|
|
# HTTPs local reverse proxying using certficates and keys provided in
|
|
# either configuration data (preferred) or relation data. Assumes ports
|
|
# are not in use (calling charm should ensure that).
|
|
# Parameters: Variable number of proxy port mappings as
|
|
# $internal:$external.
|
|
# Returns: 0 if reverse proxy(s) have been configured, 0 if not.
|
|
##########################################################################
|
|
enable_https() {
|
|
local port_maps="$@"
|
|
local http_restart=""
|
|
juju-log "Enabling HTTPS for port mappings: $port_maps."
|
|
|
|
# allow overriding of keystone provided certs with those set manually
|
|
# in config.
|
|
local cert=$(config-get ssl_cert)
|
|
local key=$(config-get ssl_key)
|
|
local ca_cert=""
|
|
if [[ -z "$cert" ]] || [[ -z "$key" ]] ; then
|
|
juju-log "Inspecting identity-service relations for SSL certificate."
|
|
local r_id=""
|
|
cert=""
|
|
key=""
|
|
ca_cert=""
|
|
for r_id in $(relation-ids identity-service) ; do
|
|
for unit in $(relation-list -r $r_id) ; do
|
|
[[ -z "$cert" ]] && cert="$(relation-get -r $r_id ssl_cert $unit)"
|
|
[[ -z "$key" ]] && key="$(relation-get -r $r_id ssl_key $unit)"
|
|
[[ -z "$ca_cert" ]] && ca_cert="$(relation-get -r $r_id ca_cert $unit)"
|
|
done
|
|
done
|
|
[[ -n "$cert" ]] && cert=$(echo $cert | base64 -di)
|
|
[[ -n "$key" ]] && key=$(echo $key | base64 -di)
|
|
[[ -n "$ca_cert" ]] && ca_cert=$(echo $ca_cert | base64 -di)
|
|
else
|
|
juju-log "Using SSL certificate provided in service config."
|
|
fi
|
|
|
|
[[ -z "$cert" ]] || [[ -z "$key" ]] &&
|
|
juju-log "Expected but could not find SSL certificate data, not "\
|
|
"configuring HTTPS!" && return 1
|
|
|
|
apt-get -y install apache2
|
|
a2enmod ssl proxy proxy_http | grep -v "To activate the new configuration" &&
|
|
http_restart=1
|
|
|
|
mkdir -p /etc/apache2/ssl/$CHARM
|
|
echo "$cert" >/etc/apache2/ssl/$CHARM/cert
|
|
echo "$key" >/etc/apache2/ssl/$CHARM/key
|
|
if [[ -n "$ca_cert" ]] ; then
|
|
juju-log "Installing Keystone supplied CA cert."
|
|
echo "$ca_cert" >/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt
|
|
update-ca-certificates --fresh
|
|
|
|
# XXX TODO: Find a better way of exporting this?
|
|
if [[ "$CHARM" == "nova-cloud-controller" ]] ; then
|
|
[[ -e /var/www/keystone_juju_ca_cert.crt ]] &&
|
|
rm -rf /var/www/keystone_juju_ca_cert.crt
|
|
ln -s /usr/local/share/ca-certificates/keystone_juju_ca_cert.crt \
|
|
/var/www/keystone_juju_ca_cert.crt
|
|
fi
|
|
|
|
fi
|
|
for port_map in $port_maps ; do
|
|
local ext_port=$(echo $port_map | cut -d: -f1)
|
|
local int_port=$(echo $port_map | cut -d: -f2)
|
|
juju-log "Creating apache2 reverse proxy vhost for $port_map."
|
|
cat >/etc/apache2/sites-available/${CHARM}_${ext_port} <<END
|
|
Listen $ext_port
|
|
NameVirtualHost *:$ext_port
|
|
<VirtualHost *:$ext_port>
|
|
ServerName $(unit-get private-address)
|
|
SSLEngine on
|
|
SSLCertificateFile /etc/apache2/ssl/$CHARM/cert
|
|
SSLCertificateKeyFile /etc/apache2/ssl/$CHARM/key
|
|
ProxyPass / http://localhost:$int_port/
|
|
ProxyPassReverse / http://localhost:$int_port/
|
|
ProxyPreserveHost on
|
|
</VirtualHost>
|
|
<Proxy *>
|
|
Order deny,allow
|
|
Allow from all
|
|
</Proxy>
|
|
<Location />
|
|
Order allow,deny
|
|
Allow from all
|
|
</Location>
|
|
END
|
|
a2ensite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
|
|
http_restart=1
|
|
done
|
|
if [[ -n "$http_restart" ]] ; then
|
|
service apache2 restart
|
|
fi
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Ensure HTTPS reverse proxying is disabled for given port
|
|
# mappings.
|
|
# Parameters: Variable number of proxy port mappings as
|
|
# $internal:$external.
|
|
# Returns: 0 if reverse proxy is not active for all portmaps, 1 on error.
|
|
##########################################################################
|
|
disable_https() {
|
|
local port_maps="$@"
|
|
local http_restart=""
|
|
juju-log "Ensuring HTTPS disabled for $port_maps."
|
|
( [[ ! -d /etc/apache2 ]] || [[ ! -d /etc/apache2/ssl/$CHARM ]] ) && return 0
|
|
for port_map in $port_maps ; do
|
|
local ext_port=$(echo $port_map | cut -d: -f1)
|
|
local int_port=$(echo $port_map | cut -d: -f2)
|
|
if [[ -e /etc/apache2/sites-available/${CHARM}_${ext_port} ]] ; then
|
|
juju-log "Disabling HTTPS reverse proxy for $CHARM $port_map."
|
|
a2dissite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
|
|
http_restart=1
|
|
fi
|
|
done
|
|
if [[ -n "$http_restart" ]] ; then
|
|
service apache2 restart
|
|
fi
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# Description: Ensures HTTPS is either enabled or disabled for given port
|
|
# mapping.
|
|
# Parameters: Variable number of proxy port mappings as
|
|
# $internal:$external.
|
|
# Returns: 0 if HTTPS reverse proxy is in place, 1 if it is not.
|
|
##########################################################################
|
|
setup_https() {
|
|
# configure https via apache reverse proxying either
|
|
# using certs provided by config or keystone.
|
|
[[ -z "$CHARM" ]] &&
|
|
error_out "setup_https(): CHARM not set."
|
|
if ! https ; then
|
|
disable_https $@
|
|
else
|
|
enable_https $@
|
|
fi
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determine correct API server listening port based on
|
|
# existence of HTTPS reverse proxy and/or haproxy.
|
|
# Paremeters: The standard public port for given service.
|
|
# Returns: The correct listening port for API service.
|
|
##########################################################################
|
|
determine_api_port() {
|
|
local public_port="$1"
|
|
local i=0
|
|
( [[ -n "$(peer_units)" ]] || is_clustered >/dev/null 2>&1 ) && i=$[$i + 1]
|
|
https >/dev/null 2>&1 && i=$[$i + 1]
|
|
echo $[$public_port - $[$i * 10]]
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Determine correct proxy listening port based on public IP +
|
|
# existence of HTTPS reverse proxy.
|
|
# Paremeters: The standard public port for given service.
|
|
# Returns: The correct listening port for haproxy service public address.
|
|
##########################################################################
|
|
determine_haproxy_port() {
|
|
local public_port="$1"
|
|
local i=0
|
|
https >/dev/null 2>&1 && i=$[$i + 1]
|
|
echo $[$public_port - $[$i * 10]]
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Print the value for a given config option in an OpenStack
|
|
# .ini style configuration file.
|
|
# Parameters: File path, option to retrieve, optional
|
|
# section name (default=DEFAULT)
|
|
# Returns: Prints value if set, prints nothing otherwise.
|
|
##########################################################################
|
|
local_config_get() {
|
|
# return config values set in openstack .ini config files.
|
|
# default placeholders starting (eg, %AUTH_HOST%) treated as
|
|
# unset values.
|
|
local file="$1"
|
|
local option="$2"
|
|
local section="$3"
|
|
[[ -z "$section" ]] && section="DEFAULT"
|
|
python -c "
|
|
import ConfigParser
|
|
config = ConfigParser.RawConfigParser()
|
|
config.read('$file')
|
|
try:
|
|
value = config.get('$section', '$option')
|
|
except:
|
|
print ''
|
|
exit(0)
|
|
if value.startswith('%'): exit(0)
|
|
print value
|
|
"
|
|
}
|
|
|
|
##########################################################################
|
|
# Description: Creates an rc file exporting environment variables to a
|
|
# script_path local to the charm's installed directory.
|
|
# Any charm scripts run outside the juju hook environment can source this
|
|
# scriptrc to obtain updated config information necessary to perform health
|
|
# checks or service changes
|
|
#
|
|
# Parameters:
|
|
# An array of '=' delimited ENV_VAR:value combinations to export.
|
|
# If optional script_path key is not provided in the array, script_path
|
|
# defaults to scripts/scriptrc
|
|
##########################################################################
|
|
function save_script_rc {
|
|
if [ ! -n "$JUJU_UNIT_NAME" ]; then
|
|
echo "Error: Missing JUJU_UNIT_NAME environment variable"
|
|
exit 1
|
|
fi
|
|
# our default unit_path
|
|
unit_path="$CHARM_DIR/scripts/scriptrc"
|
|
echo $unit_path
|
|
tmp_rc="/tmp/${JUJU_UNIT_NAME/\//-}rc"
|
|
|
|
echo "#!/bin/bash" > $tmp_rc
|
|
for env_var in "${@}"
|
|
do
|
|
if `echo $env_var | grep -q script_path`; then
|
|
# well then we need to reset the new unit-local script path
|
|
unit_path="$CHARM_DIR/${env_var/script_path=/}"
|
|
else
|
|
echo "export $env_var" >> $tmp_rc
|
|
fi
|
|
done
|
|
chmod 755 $tmp_rc
|
|
mv $tmp_rc $unit_path
|
|
}
|