334
HAPROXY_CFG=/etc/haproxy/haproxy.cfg
335
HAPROXY_DEFAULT=/etc/default/haproxy
336
##########################################################################
337
# Description: Configures HAProxy services for Openstack API's
339
# Space delimited list of service:port:mode combinations for which
340
# haproxy service configuration should be generated for. The function
341
# assumes the name of the peer relation is 'cluster' and that every
342
# service unit in the peer relation is running the same services.
344
# Services that do not specify :mode in parameter will default to http.
347
# configure_haproxy cinder_api:8776:8756:tcp nova_api:8774:8764:http
348
##########################################################################
349
configure_haproxy() {
350
local address=`unit-get private-address`
351
local name=${JUJU_UNIT_NAME////-}
352
cat > $HAPROXY_CFG << EOF
355
log 127.0.0.1 local1 notice
376
stats realm Haproxy\ Statistics
378
stats auth admin:password
381
for service in $@; do
382
local service_name=$(echo $service | cut -d : -f 1)
383
local haproxy_listen_port=$(echo $service | cut -d : -f 2)
384
local api_listen_port=$(echo $service | cut -d : -f 3)
385
local mode=$(echo $service | cut -d : -f 4)
386
[[ -z "$mode" ]] && mode="http"
387
juju-log "Adding haproxy configuration entry for $service "\
388
"($haproxy_listen_port -> $api_listen_port)"
389
cat >> $HAPROXY_CFG << EOF
390
listen $service_name 0.0.0.0:$haproxy_listen_port
394
server $name $address:$api_listen_port check
398
for r_id in `relation-ids cluster`; do
399
for unit in `relation-list -r $r_id`; do
400
local unit_name=${unit////-}
401
local unit_address=`relation-get -r $r_id private-address $unit`
402
if [ -n "$unit_address" ]; then
403
echo " server $unit_name $unit_address:$api_listen_port check" \
409
echo "ENABLED=1" > $HAPROXY_DEFAULT
410
service haproxy restart
413
##########################################################################
414
# Description: Query HA interface to determine is cluster is configured
415
# Returns: 0 if configured, 1 if not configured
416
##########################################################################
420
for r_id in $(relation-ids ha); do
421
if [ -n "$r_id" ]; then
422
for unit in $(relation-list -r $r_id); do
423
clustered=$(relation-get -r $r_id clustered $unit)
424
if [ -n "$clustered" ]; then
425
juju-log "Unit is haclustered"
431
juju-log "Unit is not haclustered"
435
##########################################################################
436
# Description: Return a list of all peers in cluster relations
437
##########################################################################
441
for r_id in $(relation-ids cluster); do
442
peers="$peers $(relation-list -r $r_id)"
447
##########################################################################
448
# Description: Determines whether the current unit is the oldest of all
449
# its peers - supports partial leader election
450
# Returns: 0 if oldest, 1 if not
451
##########################################################################
454
local l_unit_no=$(echo $JUJU_UNIT_NAME | cut -d / -f 2)
455
for peer in $peers; do
456
echo "Comparing $JUJU_UNIT_NAME with peers: $peers"
457
local r_unit_no=$(echo $peer | cut -d / -f 2)
458
if (($r_unit_no<$l_unit_no)); then
459
juju-log "Not oldest peer; deferring"
463
juju-log "Oldest peer; might take charge?"
467
##########################################################################
468
# Description: Determines whether the current service units is the
469
# leader within a) a cluster of its peers or b) across a
470
# set of unclustered peers.
471
# Parameters: CRM resource to check ownership of if clustered
472
# Returns: 0 if leader, 1 if not
473
##########################################################################
475
if is_clustered; then
476
if ! is_leader $1; then
477
juju-log 'Deferring action to CRM leader'
482
if [ -n "$peers" ] && ! oldest_peer "$peers"; then
483
juju-log 'Deferring action to oldest service unit.'
490
##########################################################################
491
# Description: Query Cluster peer interface to see if peered
492
# Returns: 0 if peered, 1 if not peered
493
##########################################################################
495
local r_id=$(relation-ids cluster)
496
if [ -n "$r_id" ]; then
497
if [ -n "$(relation-list -r $r_id)" ]; then
498
juju-log "Unit peered"
502
juju-log "Unit not peered"
506
##########################################################################
507
# Description: Determines whether host is owner of clustered services
508
# Parameters: Name of CRM resource to check ownership of
509
# Returns: 0 if leader, 1 if not leader
510
##########################################################################
513
if [ -x /usr/sbin/crm ]; then
514
if crm resource show $1 | grep -q $hostname; then
515
juju-log "$hostname is cluster leader."
519
juju-log "$hostname is not cluster leader."
523
##########################################################################
524
# Description: Determines whether enough data has been provided in
525
# configuration or relation data to configure HTTPS.
527
# Returns: 0 if HTTPS can be configured, 1 if not.
528
##########################################################################
531
if [[ -n "$(config-get ssl_cert)" ]] &&
532
[[ -n "$(config-get ssl_key)" ]] ; then
535
for r_id in $(relation-ids identity-service) ; do
536
for unit in $(relation-list -r $r_id) ; do
537
if [[ "$(relation-get -r $r_id https_keystone $unit)" == "True" ]] &&
538
[[ -n "$(relation-get -r $r_id ssl_cert $unit)" ]] &&
539
[[ -n "$(relation-get -r $r_id ssl_key $unit)" ]] &&
540
[[ -n "$(relation-get -r $r_id ca_cert $unit)" ]] ; then
548
##########################################################################
549
# Description: For a given number of port mappings, configures apache2
550
# HTTPs local reverse proxying using certficates and keys provided in
551
# either configuration data (preferred) or relation data. Assumes ports
552
# are not in use (calling charm should ensure that).
553
# Parameters: Variable number of proxy port mappings as
554
# $internal:$external.
555
# Returns: 0 if reverse proxy(s) have been configured, 0 if not.
556
##########################################################################
559
local http_restart=""
560
juju-log "Enabling HTTPS for port mappings: $port_maps."
562
# allow overriding of keystone provided certs with those set manually
564
local cert=$(config-get ssl_cert)
565
local key=$(config-get ssl_key)
567
if [[ -z "$cert" ]] || [[ -z "$key" ]] ; then
568
juju-log "Inspecting identity-service relations for SSL certificate."
573
for r_id in $(relation-ids identity-service) ; do
574
for unit in $(relation-list -r $r_id) ; do
575
[[ -z "$cert" ]] && cert="$(relation-get -r $r_id ssl_cert $unit)"
576
[[ -z "$key" ]] && key="$(relation-get -r $r_id ssl_key $unit)"
577
[[ -z "$ca_cert" ]] && ca_cert="$(relation-get -r $r_id ca_cert $unit)"
580
[[ -n "$cert" ]] && cert=$(echo $cert | base64 -di)
581
[[ -n "$key" ]] && key=$(echo $key | base64 -di)
582
[[ -n "$ca_cert" ]] && ca_cert=$(echo $ca_cert | base64 -di)
584
juju-log "Using SSL certificate provided in service config."
587
[[ -z "$cert" ]] || [[ -z "$key" ]] &&
588
juju-log "Expected but could not find SSL certificate data, not "\
589
"configuring HTTPS!" && return 1
591
apt-get -y install apache2
592
a2enmod ssl proxy proxy_http | grep -v "To activate the new configuration" &&
595
mkdir -p /etc/apache2/ssl/$CHARM
596
echo "$cert" >/etc/apache2/ssl/$CHARM/cert
597
echo "$key" >/etc/apache2/ssl/$CHARM/key
598
if [[ -n "$ca_cert" ]] ; then
599
juju-log "Installing Keystone supplied CA cert."
600
echo "$ca_cert" >/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt
601
update-ca-certificates --fresh
603
# XXX TODO: Find a better way of exporting this?
604
if [[ "$CHARM" == "nova-cloud-controller" ]] ; then
605
[[ -e /var/www/keystone_juju_ca_cert.crt ]] &&
606
rm -rf /var/www/keystone_juju_ca_cert.crt
607
ln -s /usr/local/share/ca-certificates/keystone_juju_ca_cert.crt \
608
/var/www/keystone_juju_ca_cert.crt
612
for port_map in $port_maps ; do
613
local ext_port=$(echo $port_map | cut -d: -f1)
614
local int_port=$(echo $port_map | cut -d: -f2)
615
juju-log "Creating apache2 reverse proxy vhost for $port_map."
616
cat >/etc/apache2/sites-available/${CHARM}_${ext_port} <<END
618
NameVirtualHost *:$ext_port
619
<VirtualHost *:$ext_port>
620
ServerName $(unit-get private-address)
622
SSLCertificateFile /etc/apache2/ssl/$CHARM/cert
623
SSLCertificateKeyFile /etc/apache2/ssl/$CHARM/key
624
ProxyPass / http://localhost:$int_port/
625
ProxyPassReverse / http://localhost:$int_port/
637
a2ensite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
640
if [[ -n "$http_restart" ]] ; then
641
service apache2 restart
645
##########################################################################
646
# Description: Ensure HTTPS reverse proxying is disabled for given port
648
# Parameters: Variable number of proxy port mappings as
649
# $internal:$external.
650
# Returns: 0 if reverse proxy is not active for all portmaps, 1 on error.
651
##########################################################################
654
local http_restart=""
655
juju-log "Ensuring HTTPS disabled for $port_maps."
656
( [[ ! -d /etc/apache2 ]] || [[ ! -d /etc/apache2/ssl/$CHARM ]] ) && return 0
657
for port_map in $port_maps ; do
658
local ext_port=$(echo $port_map | cut -d: -f1)
659
local int_port=$(echo $port_map | cut -d: -f2)
660
if [[ -e /etc/apache2/sites-available/${CHARM}_${ext_port} ]] ; then
661
juju-log "Disabling HTTPS reverse proxy for $CHARM $port_map."
662
a2dissite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
666
if [[ -n "$http_restart" ]] ; then
667
service apache2 restart
672
##########################################################################
673
# Description: Ensures HTTPS is either enabled or disabled for given port
675
# Parameters: Variable number of proxy port mappings as
676
# $internal:$external.
677
# Returns: 0 if HTTPS reverse proxy is in place, 1 if it is not.
678
##########################################################################
680
# configure https via apache reverse proxying either
681
# using certs provided by config or keystone.
683
error_out "setup_https(): CHARM not set."
691
##########################################################################
692
# Description: Determine correct API server listening port based on
693
# existence of HTTPS reverse proxy and/or haproxy.
694
# Paremeters: The standard public port for given service.
695
# Returns: The correct listening port for API service.
696
##########################################################################
697
determine_api_port() {
698
local public_port="$1"
700
( [[ -n "$(peer_units)" ]] || is_clustered >/dev/null 2>&1 ) && i=$[$i + 1]
701
https >/dev/null 2>&1 && i=$[$i + 1]
702
echo $[$public_port - $[$i * 10]]
705
##########################################################################
706
# Description: Determine correct proxy listening port based on public IP +
707
# existence of HTTPS reverse proxy.
708
# Paremeters: The standard public port for given service.
709
# Returns: The correct listening port for haproxy service public address.
710
##########################################################################
711
determine_haproxy_port() {
712
local public_port="$1"
714
https >/dev/null 2>&1 && i=$[$i + 1]
715
echo $[$public_port - $[$i * 10]]
718
##########################################################################
719
# Description: Print the value for a given config option in an OpenStack
720
# .ini style configuration file.
721
# Parameters: File path, option to retrieve, optional
722
# section name (default=DEFAULT)
723
# Returns: Prints value if set, prints nothing otherwise.
724
##########################################################################
726
# return config values set in openstack .ini config files.
727
# default placeholders starting (eg, %AUTH_HOST%) treated as
732
[[ -z "$section" ]] && section="DEFAULT"
735
config = ConfigParser.RawConfigParser()
738
value = config.get('$section', '$option')
742
if value.startswith('%'): exit(0)
747
##########################################################################
748
# Description: Creates an rc file exporting environment variables to a
749
# script_path local to the charm's installed directory.
750
# Any charm scripts run outside the juju hook environment can source this
751
# scriptrc to obtain updated config information necessary to perform health
752
# checks or service changes
755
# An array of '=' delimited ENV_VAR:value combinations to export.
756
# If optional script_path key is not provided in the array, script_path
757
# defaults to scripts/scriptrc
758
##########################################################################
759
function save_script_rc {
760
if [ ! -n "$JUJU_UNIT_NAME" ]; then
761
echo "Error: Missing JUJU_UNIT_NAME environment variable"
764
# our default unit_path
765
unit_path="$CHARM_DIR/scripts/scriptrc"
767
tmp_rc="/tmp/${JUJU_UNIT_NAME/\//-}rc"
769
echo "#!/bin/bash" > $tmp_rc
770
for env_var in "${@}"
772
if `echo $env_var | grep -q script_path`; then
773
# well then we need to reset the new unit-local script path
774
unit_path="$CHARM_DIR/${env_var/script_path=/}"
776
echo "export $env_var" >> $tmp_rc
780
mv $tmp_rc $unit_path