Refactor to use common Openstack code. Allow upgrades from essex to folsom.

This commit is contained in:
Adam Gandelman 2012-10-01 15:17:24 -07:00
parent 34d000806a
commit 084bb19682
6 changed files with 316 additions and 142 deletions

View File

@ -3,14 +3,6 @@ options:
default: distro
type: string
description: Glance PPA from which to install. (distro, trunk, milestone, milestone-proposed or ppa:somewhere/else)
api-config:
default: /etc/glance/glance-api.conf
type: string
description: Full path to Glance API configuration.
registry-config:
default: /etc/glance/glance-registry.conf
type: string
description: Full path to Glance registry configuration.
db-user:
default: glance
type: string

1
hooks/config-changed Symbolic link
View File

@ -0,0 +1 @@
glance-relations

View File

@ -1,55 +1,21 @@
#$!/bin/bash
#!/bin/bash
CHARM="glance"
SERVICES="glance-api glance-registry"
PACKAGES="glance python-mysqldb python-swift python-keystone"
PACKAGES="glance python-mysqldb python-swift python-keystone uuid"
GLANCE_REGISTRY_CONF=$(config-get registry-config)
GLANCE_REGISTRY_CONF="/etc/glance/glance-registry.conf"
GLANCE_REGISTRY_PASTE_INI="/etc/glance/glance-registry-paste.ini"
GLANCE_API_CONF=$(config-get api-config)
GLANCE_API_CONF="/etc/glance/glance-api.conf"
GLANCE_API_PASTE_INI="/etc/glance/glance-api-paste.ini"
CONF_DIR="/etc/glance"
DB_USER=$(config-get db-user)
GLANCE_DB=$(config-get glance-db)
PPA=$(config-get glance-release)
HOSTNAME=`hostname -f`
function glance_ctl_status {
SERVICE=$1
# workaround upstarts lack of scriptable return codes
STATUS=$(service $SERVICE status | cut -d/ -f1 | awk '{ print $2 }')
case $STATUS in
"start") return 0 ;;
"stop") return 1 ;;
*) echo "ERROR: Unexpected status of service $SERVICE: $STATUS" && exit 1 ;;
esac
}
function glance_ctl {
if [[ $1 == "all" ]] ; then
CTL=$SERVICES
else
CTL=$1
fi
ACTION=$2
if [[ -z $CTL ]] || [[ -z $ACTION ]] ; then
juju-log "ERROR glance_ctl: Not enough arguments"
exit 1
fi
for i in $CTL ; do
case $ACTION in
"start")
glance_ctl_status $i || service $i start ;;
"stop")
glance_ctl_status $i && service $i stop || return 0 ;;
"restart")
glance_ctl_status $i && service $i restart || service $i start ;;
esac
if [[ $? != 0 ]] ; then
juju-log "glance_ctl: ERROR - Service $i failed to $ACTION"
fi
done
}
if [[ -e "$CHARM_DIR/lib/openstack-common" ]] ; then
. $CHARM_DIR/lib/openstack-common
else
juju-log "ERROR: Couldn't load $CHARM_DIR/lib/openstack-common." && exit 1
fi
function set_paste_deploy_flavor {
local flavor="$1"
@ -58,7 +24,7 @@ function set_paste_deploy_flavor {
"api") local conf=$GLANCE_API_CONF ;;
"registry") local conf=$GLANCE_REGISTRY_CONF ;;
*) juju-log "ERROR: set_paste_deploy: invalid config=$config" && exit 1 ;;
esac
esac
if ! grep -q "\[paste_deploy\]" "$conf" ; then
juju-log "Updating $conf: Setting new paste_deploy flavor = $flavor"
echo -e "\n[paste_deploy]\nflavor = keystone\n" >>$conf && return 0
@ -80,7 +46,7 @@ function update_pipeline {
"api") local api_conf=$GLANCE_API_CONF ;;
"registry") local api_conf=$GLANCE_REGISTRY_CONF ;;
*) juju-log "ERROR: update_pipeline: invalid config=$config" && exit 1 ;;
esac
esac
local tag="\[pipeline:$pipeline\]"
if ! grep -q "$tag" $api_conf ; then
@ -119,42 +85,37 @@ function set_or_update {
fi
}
function add_ppa {
# Install from archive instead of PPA.
[[ $PPA == "distro" ]] && return 0
. /etc/lsb-release
[[ -z $PPA ]] && return 0
# if referenced by name, setup ppa to upstream PPAs
if [[ "$PPA" == "trunk" ]] ||
[[ "$PPA" == "milestone" ]] ||
[[ "$PPA" == "milestone-proposed" ]] ; then
juju-log "glance: Configuring installation from upstream PPA ($PPA)"
PPA_URL="deb http://ppa.launchpad.net/glance-core/$PPA/ubuntu $DISTRIB_CODENAME main"
add-apt-repository "$PPA_URL" || exit 1
return
do_openstack_upgrade() {
# update openstack components to those provided by a new installation source
# it is assumed the calling hook has confirmed that the upgrade is sane.
local rel="$1"
shift
local packages=$@
orig_os_rel=$(get_os_codename_package "glance-common")
new_rel=$(get_os_codename_install_source "$rel")
# Backup the config directory.
local stamp=$(date +"%Y%m%d%M%S")
tar -pcf /var/lib/juju/$CHARM-backup-$stamp.tar $CONF_DIR
# Setup apt repository access and kick off the actual package upgrade.
configure_install_source "$rel"
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get --option Dpkg::Options::=--force-confnew -y \
install --no-install-recommends $packages
# Update the new config files for existing relations.
local r_id=""
r_id=$(relation-ids shared-db)
if [[ -n "$r_id" ]] ; then
juju-log "$CHARM: Configuring database after upgrade to $rel."
db_changed $r_id
fi
if [[ "${PPA:0:4}" == "ppa:" ]] ; then
juju-log "glance: Configuring installation from custom PPA ($PPA)"
add-apt-repository -y "$PPA" || exit 1
return
r_id=$(relation-ids identity-service)
if [[ -n "$r_id" ]] ; then
juju-log "$CHARM: Configuring identity service after upgrade to $rel."
keystone_changed $r_id
fi
if [[ "${PPA:0:3}" == "deb" ]] ; then
juju-log "glance: Configuring installation from custom PPA URL ($PPA)"
if echo "$PPA" | grep -q "|" ; then
# gpg key id tagged to end of url folloed by a |
url=$(echo $PPA | cut -d'|' -f1)
key=$(echo $PPA | cut -d'|' -f2)
if [[ -n "$key" ]] ; then
juju-log "Importing repository key: $key"
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$key" || \
juju-log "WARN: Could not import key from keyserver: $key"
else
juju-log "No repository key specified"
url="$PPA"
fi
add-apt-repository -y "$url"
fi
return
fi
juju-log "glance: No PPA specified. Falling back to installation from Ubuntu archive."
}

View File

@ -1,33 +1,26 @@
#!/bin/bash
#!/bin/bash -e
FORMULA_DIR=$(dirname $0)
CHARM_DIR=$(dirname $0)
ARG0=${0##*/}
if [[ -e $FORMULA_DIR/glance-common ]] ; then
. $FORMULA_DIR/glance-common
if [[ -e $CHARM_DIR/glance-common ]] ; then
. $CHARM_DIR/glance-common
else
echo "ERROR: Could nto load glance-common from $FORMULA_DIR"
echo "ERROR: Could nto load glance-common from $CHARM_DIR"
fi
function install_hook {
juju-log "Installing glance packages"
apt-get -y install python-software-properties || exit 1
add_ppa
configure_install_source $(config-get glance-release)
apt-get update || exit 1
apt-get -y install $PACKAGES || exit 1
glance_ctl all stop
service_ctl all stop
# work around LP #784837 until its fixed.
[[ ! -d /var/log/glance ]] && mkdir /var/log/glance
chown glance /var/log/glance
[[ ! -e /var/log/glance/api.log ]] && touch /var/log/glance/api.log
[[ ! -e /var/log/glance/registry.log ]] && touch /var/log/glance/registry.log
chown glance /var/log/glance/*.log
# XXX turn up the logging for now.
# TODO: Make debug logging a config option.
set_or_update verbose True api
set_or_update debug True api
set_or_update verbose True registry
@ -35,33 +28,66 @@ function install_hook {
}
function db_joined {
juju-log "glance: db_joined: requesting access to $GLANCE_DB for $DB_USER@`unit-get private-address`"
relation-set database=$GLANCE_DB
relation-set username=$DB_USER
relation-set hostname=`unit-get private-address`
local glance_db=$(config-get glance-db)
local db_user=$(config-get db-user)
local hostname=$(unit-get private-address)
juju-log "$CHARM - db_joined: requesting database access to $glance_db for "\
"$db_user@$hostname"
relation-set database=$glance_db username=$db_user hostname=$hostname
}
function db_changed {
DB_HOST=`relation-get private-address`
DB_PASSWORD=`relation-get password`
if [[ -z $DB_HOST ]] || [[ -z $DB_PASSWORD ]] ; then
echo "db_changed: DB_HOST || DB_PASSWORD not yet set. Exit 0 and retry"
# serves as the main shared-db changed hook but may also be called with a
# relation-id to configure new config files for existing relations.
local r_id="$1"
local r_args=""
if [[ -n "$r_id" ]] ; then
# set up environment for an existing relation to a single unit.
export JUJU_REMOTE_UNIT=$(relation-list -r $r_id | head -n1)
export JUJU_RELATION="shared-db"
export JUJU_RELATION_ID="$r_id"
local r_args="-r $JUJU_RELATION_ID"
juju-log "$CHARM - db_changed: Running hook for existing relation to "\
"$JUJU_REMOTE_UNIT-$JUJU_RELATION_ID"
fi
local db_host=$(relation-get $r_args private-address)
local db_password=$(relation-get $r_args password)
if [[ -z "$db_host" ]] || [[ -z "$db_password" ]] ; then
juju-log "$CHARM - db_changed: db_host||db_password set, will retry."
exit 0
else
echo "db_changed: Received password from $DB_HOST"
fi
juju-log "glance: db_changed: Configuring registry for access to $GLANCE_DB@$DB_HOST"
glance_ctl all stop
set_or_update sql_connection "mysql://$DB_USER:$DB_PASSWORD@$DB_HOST/$GLANCE_DB" registry
set_or_update sql_connection "mysql://$DB_USER:$DB_PASSWORD@$DB_HOST/$GLANCE_DB" api
# Set the db version to 0 if its not under version control. We assume that any existing
# database we are being related to was created WITH version control.
if ! glance-manage db_version ; then
juju-log "Setting glance database version to 0"
glance-manage version_control 0
local glance_db=$(config-get glance-db)
local db_user=$(config-get db-user)
local rel=$(get_os_codename_package glance-common)
if [[ -n "$r_id" ]] ; then
unset JUJU_REMOTE_UNIT JUJU_RELATION JUJU_RELATION_ID
fi
juju-log "$CHARM - db_changed: Configuring glance.conf for access to $glance_db"
service_ctl all stop
set_or_update sql_connection "mysql://$db_user:$db_password@$db_host/$glance_db" registry
# folsom requires a db connection setting in glance-api.conf, as well.
[[ "$rel" == "folsom" ]] &&
set_or_update sql_connection "mysql://$db_user:$db_password@$db_host/$glance_db" api
if [[ "$rel" == "essex" ]] ; then
# Essex required initializing new databases to version 0
if ! glance-manage db_version >/dev/null 2>&1; then
juju-log "Setting glance database version to 0"
glance-manage version_control 0
fi
fi
juju-log "$CHARM - db_changed: Running database migrations for $rel."
glance-manage db_sync
glance_ctl all restart
service_ctl all restart
}
function image-service_joined {
@ -83,7 +109,7 @@ function object-store_changed {
set_or_update swift_store_key $PASSWORD api
set_or_update swift_store_auth_address $URL api
set_or_update swift_store_create_container_on_put true api
glance_ctl glance-api restart
service_ctl glance-api restart
}
function keystone_joined {
@ -94,13 +120,26 @@ function keystone_joined {
}
function keystone_changed {
# we hopefully get a token in return. configure middleware accordingly
token=$(relation-get admin_token)
service_port=$(relation-get service_port)
auth_port=$(relation-get auth_port)
service_username=$(relation-get service_username)
service_password=$(relation-get service_password)
service_tenant=$(relation-get service_tenant)
# serves as the main identity-service changed hook, but may also be called
# with a relation-id to configure new config files for existing relations.
local r_id="$1"
local r_args=""
if [[ -n "$r_id" ]] ; then
# set up environment for an existing relation to a single unit.
export JUJU_REMOTE_UNIT=$(relation-list -r $r_id | head -n1)
export JUJU_RELATION="identity-service"
export JUJU_RELATION_ID="$r_id"
local r_args="-r $JUJU_RELATION_ID"
juju-log "$CHARM - db_changed: Running hook for existing relation to "\
"$JUJU_REMOTE_UNIT-$JUJU_RELATION_ID"
fi
token=$(relation-get $r_args $r_args admin_token)
service_port=$(relation-get $r_args service_port)
auth_port=$(relation-get $r_args auth_port)
service_username=$(relation-get $r_args service_username)
service_password=$(relation-get $r_args service_password)
service_tenant=$(relation-get $r_args service_tenant)
[[ -z "$token" ]] || [[ -z "$service_port" ]] || [[ -z "$auth_port" ]] ||
[[ -z "$service_username" ]] || [[ -z "$service_password" ]] ||
[[ -z "$service_tenant" ]] && juju-log "keystone_changed: Peer not ready" &&
@ -108,7 +147,11 @@ function keystone_changed {
[[ "$token" == "-1" ]] &&
juju-log "keystone_changed: admin token error" && exit 1
juju-log "keystone_changed: Acquired admin. token"
keystone_host=$(relation-get private-address)
keystone_host=$(relation-get $r_args private-address)
if [[ -n "$r_id" ]] ; then
unset JUJU_REMOTE_UNIT JUJU_RELATION JUJU_RELATION_ID
fi
set_paste_deploy_flavor "keystone" "api" || exit 1
set_paste_deploy_flavor "keystone" "registry" || exit 1
@ -122,14 +165,31 @@ function keystone_changed {
set_or_update "admin_token" "$token" $i
set_or_update "admin_tenant_name" "$service_tenant" $i
set_or_update "admin_user" "$service_username" $i
set_or_update "admin_password" "$service_password" $i
done
glance_ctl all restart
set_or_update "admin_password" "$service_password" $i
done
service_ctl all restart
}
function config_changed() {
# Determine whether or not we should do an upgrade, based on whether or not
# the version offered in glance-release is greater than what is installed.
local install_src=$(config-get glance-release)
local cur=$(get_os_codename_package "glance-common")
local available=$(get_os_codename_install_source "$install_src")
if dpkg --compare-versions $(get_os_version_codename "$cur") lt \
$(get_os_version_codename "$available") ; then
juju-log "$CHARM: Upgrading OpenStack release: $cur -> $available."
do_openstack_upgrade "$install_src" $PACKAGES
fi
service_ctl all restart
}
case $ARG0 in
"start"|"stop") glance_ctl all $ARG0 ;;
"start"|"stop") service_ctl all $ARG0 ;;
"install") install_hook ;;
"config-changed") config_changed ;;
"shared-db-relation-joined") db_joined ;;
"shared-db-relation-changed") db_changed;;
"image-service-relation-joined") image-service_joined ;;
@ -139,4 +199,3 @@ case $ARG0 in
"identity-service-relation-joined") keystone_joined ;;
"identity-service-relation-changed") keystone_changed ;;
esac

161
hooks/lib/openstack-common Normal file
View File

@ -0,0 +1,161 @@
#!/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)
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")
service_ctl_status $i && service $i restart || service $i start ;;
esac
if [[ $? != 0 ]] ; then
juju-log "$CHARM: service_ctl ERROR - Service $i failed to $action"
fi
done
}
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)
if [[ -n "$key" ]] ; then
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
add-apt-repository -y "$url"
fi
return 0
fi
# Cloud Archive
if [[ "${src:0:6}" == "cloud:" ]] ; then
local archive_key="5EDB1B62EC4926EA"
local rel=$(echo $src | cut -d: -f2)
local u_rel=$(echo $rel | cut -d- -f1)
local ca_rel=$(echo $rel | cut -d- -f2)
[[ "$u_rel" != "$DISTRIB_CODENAME" ]] &&
error_out "Cannot install from Cloud Archive pocket $src " \
"on this Ubuntu version ($DISTRIB_CODENAME)!"
case "$ca_rel" in
"folsom"|"folsom/updates") pocket="precise-updates/folsom" ;;
"folsom/proposed") pocket="precise-proposed/folsom" ;;
*) error_out "Invalid Cloud Archive repo specified: $src"
esac
entry="deb http://ubuntu-cloud.archive.canonical.com/ubuntu $pocket main"
echo "$entry" \
>/etc/apt/sources.list.d/ubuntu-cloud-archive-$DISTRIB_CODENAME.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $archive_key
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" ;;
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" ;;
esac
fi
fi
echo $codename
}
get_os_codename_package() {
local pkg_vers=$(dpkg -l | grep "$1" | awk '{ print $3 }')
case "${pkg_vers:0:6}" in
"2011.2") echo "diablo" ;;
"2012.1") echo "essex" ;;
"2012.2") echo "folsom" ;;
"2013.1") echo "grizzly" ;;
esac
}
get_os_version_codename() {
case "$1" in
"diablo") echo "2011.2" ;;
"essex") echo "2012.1" ;;
"folsom") echo "2012.2" ;;
"grizzly") echo "2012.3" ;;
esac
}

View File

@ -1 +1 @@
65
66