diff --git a/config.yaml b/config.yaml index 73f5c6f..81e073a 100644 --- a/config.yaml +++ b/config.yaml @@ -1,8 +1,19 @@ options: - nova-release: + openstack-origin: default: distro type: string - description: Nova PPA from which to install. (distro, trunk, milestone, milestone-proposed) + description: | + Repository from which to install. May be one of the following: + distro (default), ppa:somecustom/ppa, a deb url sources entry, + or a supported Cloud Archive release pocket. + + Supported Cloud Archive sources include: cloud:precise-folsom, + cloud:precise-folsom/updates, cloud:precise-folsom/staging, + cloud:precise-folsom/proposed. + + Note that updating this setting to a source that is known to + provide a later version of OpenStack will trigger a software + upgrade. nova-config: default: /etc/nova/nova.conf type: string diff --git a/hooks/identity-service-relation-changed b/hooks/cloud-compute-relation-changed similarity index 100% rename from hooks/identity-service-relation-changed rename to hooks/cloud-compute-relation-changed diff --git a/hooks/identity-service-relation-joined b/hooks/cloud-compute-relation-joined similarity index 100% rename from hooks/identity-service-relation-joined rename to hooks/cloud-compute-relation-joined diff --git a/hooks/lib/nova/essex b/hooks/lib/nova/essex new file mode 100644 index 0000000..691fbbb --- /dev/null +++ b/hooks/lib/nova/essex @@ -0,0 +1,42 @@ +#!/bin/bash -e + +# Essex-specific functions + +nova_set_or_update() { + # Set a config option in nova.conf or api-paste.ini, depending + # Defaults to updating nova.conf + local key=$1 + local value=$2 + local conf_file=$3 + local pattern="" + + local nova_conf=${NOVA_CONF:-/etc/nova/nova.conf} + local api_conf=${API_CONF:-/etc/nova/api-paste.ini} + + [[ -z $key ]] && juju-log "$CHARM set_or_update: value $value missing key" && exit 1 + [[ -z $value ]] && juju-log "$CHARM set_or_update: key $key missing value" && exit 1 + [[ -z "$conf_file" ]] && conf_file=$nova_conf + + case "$conf_file" in + "$nova_conf") match="\-\-$key=" + pattern="--$key=" + out=$pattern + ;; + "$api_conf") match="^$key = " + pattern="$match" + out="$key = " + ;; + *) error_out "ERROR: set_or_update: Invalid conf_file ($conf_file)" + esac + + cat $conf_file | grep "$match$value" >/dev/null && + juju-log "$CHARM: $key=$value already in set in $conf_file" \ + && return 0 + if cat $conf_file | grep "$match" >/dev/null ; then + juju-log "$CHARM: Updating $conf_file, $key=$value" + sed -i "s|\($pattern\).*|\1$value|" $conf_file + else + juju-log "$CHARM: Setting new option $key=$value in $conf_file" + echo "$out$value" >>$conf_file + fi +} diff --git a/hooks/lib/nova/folsom b/hooks/lib/nova/folsom new file mode 100644 index 0000000..d80bb8b --- /dev/null +++ b/hooks/lib/nova/folsom @@ -0,0 +1,112 @@ +#!/bin/bash -e + +# Folsom-specific functions + +nova_set_or_update() { + # Set a config option in nova.conf or api-paste.ini, depending + # Defaults to updating nova.conf + local key="$1" + local value="$2" + local conf_file="$3" + + local nova_conf=${NOVA_CONF:-/etc/nova/nova.conf} + local api_conf=${API_CONF:-/etc/nova/api-paste.ini} + + [[ -z $key ]] && juju-log "$CHARM: set_or_update: value $value missing key" && exit 1 + [[ -z $value ]] && juju-log "$CHARM: set_or_update: key $key missing value" && exit 1 + + [[ -z "$conf_file" ]] && conf_file=$nova_conf + + local pattern="" + case "$conf_file" in + "$nova_conf") match="^$key=" + pattern="$key=" + out=$pattern + ;; + "$api_conf") match="^$key = " + pattern="$match" + out="$key = " + ;; + *) juju-log "$CHARM ERROR: set_or_update: Invalid conf_file ($conf_file)" + esac + + cat $conf_file | grep "$match$value" >/dev/null && + juju-log "$CHARM: $key=$value already in set in $conf_file" \ + && return 0 + if cat $conf_file | grep "$match" >/dev/null ; then + juju-log "$CHARM: Updating $conf_file, $key=$value" + sed -i "s|\($pattern\).*|\1$value|" $conf_file + else + juju-log "$CHARM: Setting new option $key=$value in $conf_file" + echo "$out$value" >>$conf_file + fi +} + +# Upgrade Helpers +nova_pre_upgrade() { + # Pre-upgrade helper. Caller should pass the version of OpenStack we are + # upgrading from. + return 0 # Nothing to do here, yet. +} + +nova_post_upgrade() { + # Post-upgrade helper. Caller should pass the version of OpenStack we are + # upgrading from. + local upgrade_from="$1" + juju-log "$CHARM: Running post-upgrade hook: $upgrade_from -> folsom." + # We only support essex -> folsom, currently. + [[ "$upgrade_from" != "essex" ]] && + error_out "Unsupported upgrade: $upgrade_from -> folsom" + + # This may be dangerous, if we are upgrading a number of units at once + # and they all begin the same migration concurrently. Migrate only from + # the cloud controller(s). + if [[ "$CHARM" == "nova-cloud-controller" ]] ; then + juju-log "$CHARM: Migrating nova database." + /usr/bin/nova-manage db sync + + # Trigger a service restart on all other nova nodes. + trigger_remote_service_restarts + fi + + # Packaging currently takes care of converting the Essex gflags format + # to .ini, but we need to update the api-paste.ini manually. It can be + # updated directly from keystone, via the identity-service relation, + # if it exists. Only services that require keystone credentials will + # have modified api-paste.ini, and only those services will have a .dpkg-dist + # version present. + local r_id=$(relation-ids identity-service) + if [[ -n "$r_id" ]] && [[ -e "$CONF_DIR/api-paste.ini.dpkg-dist" ]] ; then + # Backup the last api config, update the stock packaged version + # with our current Keystone info. + mv $API_CONF $CONF_DIR/api-paste.ini.juju-last + mv $CONF_DIR/api-paste.ini.dpkg-dist $CONF_DIR/api-paste.ini + + unit=$(relation-list -r $r_id | head -n1) + # Note, this should never be called from an relation hook, only config-changed. + export JUJU_REMOTE_UNIT=$unit + service_port=$(relation-get -r $r_id service_port) + auth_port=$(relation-get -r $r_id auth_port) + service_username=$(relation-get -r $r_id service_username) + service_password=$(relation-get -r $r_id service_password) + service_tenant=$(relation-get -r $r_id service_tenant) + keystone_host=$(relation-get -r $r_id private-address) + unset JUJU_REMOTE_UNIT + + juju-log "$CHARM: Updating new api-paste.ini with keystone data from $unit:$r_id" + set_or_update "service_host" "$keystone_host" "$API_CONF" + set_or_update "service_port" "$service_port" "$API_CONF" + set_or_update "auth_host" "$keystone_host" "$API_CONF" + set_or_update "auth_port" "$auth_port" "$API_CONF" + set_or_update "auth_uri" "http://$keystone_host:$service_port/" "$API_CONF" + set_or_update "admin_tenant_name" "$service_tenant" "$API_CONF" + set_or_update "admin_user" "$service_username" "$API_CONF" + set_or_update "admin_password" "$service_password" "$API_CONF" + fi + + # TEMPORARY + # RC3 packaging in cloud archive doesn't have this in postinst. Do it here + sed -e "s,^root_helper=.\+,rootwrap_config=/etc/nova/rootwrap.conf," -i /etc/nova/nova.conf + + juju-log "$CHARM: Post-upgrade hook complete: $upgrade_from -> folsom." +} diff --git a/hooks/lib/nova/nova-common b/hooks/lib/nova/nova-common new file mode 100644 index 0000000..e3307ac --- /dev/null +++ b/hooks/lib/nova/nova-common @@ -0,0 +1,103 @@ +#!/bin/bash -e + +# Common utility functions used across all nova charms. + +# Load the common OpenStack helper library. +if [[ -e $CHARM_DIR/lib/openstack-common ]] ; then + . $CHARM_DIR/lib/openstack-common +else + juju-log "Couldn't load $CHARM_DIR/lib/opentack-common." && exit 1 +fi + +set_or_update() { + # Update config flags in nova.conf or api-paste.ini. + # Config layout changed in Folsom, so this is now OpenStack release specific. + local rel=$(get_os_codename_package "nova-common") + . $CHARM_DIR/lib/nova/$rel + nova_set_or_update $@ +} + +function set_config_flags() { + # Set user-defined nova.conf flags from deployment config + juju-log "$CHARM: Processing config-flags." + flags=$(config-get config-flags) + if [[ "$flags" != "None" && -n "$flags" ]] ; then + for f in $(echo $flags | sed -e 's/,/ /g') ; do + k=$(echo $f | cut -d= -f1) + v=$(echo $f | cut -d= -f2) + set_or_update "$k" "$v" + done + fi +} + +configure_volume_service() { + local svc="$1" + case "$svc" in + "cinder") set_or_update "volume_api_class" "nova.volume.cinder.API" ;; + "nova-volume") set_or_update "volume_api_class" "nova.volume.api.API" ;; + *) juju-log "$CHARM ERROR - configure_volume_service: Invalid service $svc" + return 1 ;; + esac +} + +function configure_network_manager { + local manager="$1" + echo "$CHARM: configuring $manager network manager" + case $1 in + "FlatManager") + set_or_update "network_manager" "nova.network.manager.FlatManager" + ;; + "FlatDHCPManager") + set_or_update "network_manager" "nova.network.manager.FlatDHCPManager" + ;; + *) echo "ERROR: Invalid network manager $1" && exit 1 ;; + esac +} + +function trigger_remote_service_restarts() { + # Trigger a service restart on all other nova nodes that have a relation + # via the cloud-controller interface. + + # possible relations to other nova services. + local relations="cloud-compute nova-volume-service" + + for rel in $relations; do + local r_ids=$(relation-ids $rel) + for r_id in $r_ids ; do + juju-log "$CHARM: Triggering a service restart on relation $r_id." + relation-set -r $r_id restart-trigger=$(uuid) + done + done +} + +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 "nova-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 + + # load the release helper library for pre/post upgrade hooks specific to the + # release we are upgrading to. + . $CHARM_DIR/lib/nova/$new_rel + + # new release specific pre-upgrade hook + nova_pre_upgrade "$orig_os_rel" + + # 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-confold -y \ + install --no-install-recommends $packages + + # new release sepcific post-upgrade hook + nova_post_upgrade "$orig_os_rel" + +} diff --git a/hooks/lib/openstack-common b/hooks/lib/openstack-common new file mode 100644 index 0000000..7ce1bdd --- /dev/null +++ b/hooks/lib/openstack-common @@ -0,0 +1,167 @@ +#!/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)!" + + if [[ "$ca_rel" == "folsom/staging" ]] ; then + # cloud archive staging is just a regular PPA. + add-apt-repository -y ppa:ubuntu-cloud-archive/folsom-staging + return 0 + fi + + 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 +} diff --git a/hooks/network-manager-relation-changed b/hooks/network-manager-relation-changed deleted file mode 120000 index 6f9ff4f..0000000 --- a/hooks/network-manager-relation-changed +++ /dev/null @@ -1 +0,0 @@ -nova-compute-relations \ No newline at end of file diff --git a/hooks/network-manager-relation-joined b/hooks/network-manager-relation-joined deleted file mode 120000 index 6f9ff4f..0000000 --- a/hooks/network-manager-relation-joined +++ /dev/null @@ -1 +0,0 @@ -nova-compute-relations \ No newline at end of file diff --git a/hooks/nova-compute-common b/hooks/nova-compute-common index 4e65bf9..d1bd21f 100755 --- a/hooks/nova-compute-common +++ b/hooks/nova-compute-common @@ -1,101 +1,32 @@ -#!/bin/bash -SERVICES="nova-compute nova-network nova-api" -NOVA_RELEASE=$(config-get nova-release) +#!/bin/bash -e + +CHARM="nova-compute" +PACKAGES="nova-compute nova-api nova-network python-keystone" +SERVICES="nova-compute nova-api nova-network" +CONF_DIR="/etc/nova" NOVA_CONF=$(config-get nova-config) -RABBIT_USER=$(config-get rabbit-user) -RABBIT_VHOST=$(config-get rabbit-vhost) -DB_USER=$(config-get db-user) -NOVA_DB=$(config-get nova-db) -NETWORK_MANAGER=$(config-get network-manager) -NETWORK_BRIDGE=$(config-get bridge-interface) -BRIDGE_IP=$(config-get bridge-ip) -BRIDGE_NETMASK=$(config-get bridge-netmask) -PPA=$(config-get nova-release) -VIRT_TYPE=$(config-get virt-type) +API_CONF="/etc/nova/api-paste.ini" -function set_or_update { - # Set a config option in nova.conf or api-paste.ini, depending - # Defaults to updating nova.conf - local KEY=$1 - local VALUE=$2 - local CONF_FILE=$3 - local pattern="" - [[ -z $KEY ]] && juju-log "set_or_update: value $VALUE missing KEY" && exit 1 - [[ -z $VALUE ]] && juju-log "set_or_update: key $KEY missing VALUE" && exit 1 - [[ -z "$CONF_FILE" ]] && CONF_FILE=$NOVA_CONF +if [[ -e $CHARM_DIR/lib/nova/nova-common ]] ; then + . $CHARM_DIR/lib/nova/nova-common +else + juju-log "$CHARM: Couldn't load $CHARM_DIR/lib/nova-common" && exit 1 +fi - case "$CONF_FILE" in - "$NOVA_CONF") match="^$KEY=" - pattern="$KEY=" - out=$pattern - ;; - "$API_CONF") match="^$KEY = " - pattern="$match" - out="$KEY = " - ;; - *) juju-log "ERROR: set_or_update: Invalid CONF_FILE ($CONF_FILE)" +determine_compute_package() { + # determines the appropriate nova-compute package to install + # for the configured virt-type. + local virt_type="$1" + local compute_pkg="" + case $virt_type in + "kvm") compute_pkg="nova-compute-kvm";; + "qemu") compute_pkg="nova-compute-qemu";; + "xen") compute_pkg="nova-compute-xen";; + "uml") compute_pkg="nova-compute-uml";; + "lxc") compute_pkg="nova-compute-lxc";; + *) error_out" ERROR: Unsupported virt_type=$virt_type";; esac - - cat $CONF_FILE | grep "$match$VALUE" >/dev/null && - juju-log "nova-cloud-controller: $KEY=$VALUE already in set in $CONF_FILE" \ - && return 0 - if cat $CONF_FILE | grep "$match" >/dev/null ; then - juju-log "nova-cloud-controller: Updating $CONF_FILE, $KEY=$VALUE" - sed -i "s|\($pattern\).*|\1$VALUE|" $CONF_FILE - else - juju-log "nova-cloud-controller: Setting new option $KEY=$VALUE in $CONF_FILE" - echo "$out$VALUE" >>$CONF_FILE - fi -} - -function set_config_flags() { - # Set user-defined nova.conf flags from deployment config - juju-log "Processing config-flags." - flags=$(config-get config-flags) - if [[ "$flags" != "None" && -n "$flags" ]] ; then - for f in $(echo $flags | sed -e 's/,/ /g') ; do - k=$(echo $f | cut -d= -f1) - v=$(echo $f | cut -d= -f2) - set_or_update "$k" "$v" - done - fi -} - -function nova_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 nova_ctl { - if [[ $1 == "all" ]] ; then - CTL=$SERVICES - else - CTL=$1 - fi - ACTION=$2 - if [[ -z $CTL ]] || [[ -z $ACTION ]] ; then - juju-log "ERROR nova_ctl: Not enough arguments" - exit 1 - fi - for i in $CTL ; do - case $ACTION in - "start") - nova_ctl_status $i || service $i start ;; - "stop") - nova_ctl_status $i && service $i stop || return 0 ;; - "restart") - nova_ctl_status $i && service $i restart || service $i start ;; - esac - if [[ $? != 0 ]] ; then - juju-log "nova_ctl: ERROR - Service $i failed to $ACTION" - fi - done + echo "$compute_pkg" } function setup_bridge { @@ -129,65 +60,27 @@ function configure_network_manager { # to be expanded later to cover flatDhcp and VLAN echo "$0: configuring $1 network manager" - NETWORK_BRIDGE=$(config-get bridge-interface) + local network_bridge=$(config-get bridge-interface) case $1 in "FlatManager") - setup_bridge $NETWORK_BRIDGE $BRIDGE_IP $BRIDGE_NETMASK + local bridge_ip=$(config-get bridge-ip) + local bridge_netmask=$(config-get bridge-netmask) + setup_bridge $network_bridge $bridge_ip $bridge_netmask set_or_update network_manager nova.network.manager.FlatManager - set_or_update flat_network_bridge $NETWORK_BRIDGE + set_or_update flat_network_bridge $network_bridge ;; "FlatDHCPManager") - FLAT_INTERFACE=$(config-get flat-interface) - EC2_HOST=$(relation-get ec2_host) - [[ -z $EC2_HOST ]] && juju-log "nova-compute: Missing EC2_HOST" \ + local flat_interface=$(config-get flat-interface) + local ec2_host=$(relation-get ec2_host) + [[ -z $ec2_host ]] && juju-log "nova-compute: Missing ec2_host" \ && exit 0 set_or_update network_manager nova.network.manager.FlatDHCPManager # the interface on which bridge is built - set_or_update flat_interface $FLAT_INTERFACE + set_or_update flat_interface $flat_interface # address of API server to forward requests - set_or_update ec2_dmz_host $EC2_HOST + set_or_update ec2_dmz_host $ec2_host ;; *) echo "ERROR: Invalid network manager $1" && exit 1 ;; esac } - -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 "nova: Configuring installation from upstream PPA ($PPA)" - PPA_URL="deb http://ppa.launchpad.net/nova-core/$PPA/ubuntu $DISTRIB_CODENAME main" - add-apt-repository "$PPA_URL" || exit 1 - return - fi - if [[ "${PPA:0:4}" == "ppa:" ]] ; then - juju-log "nova: Configuring installation from custom PPA ($PPA)" - add-apt-repository -y "$PPA" || exit 1 - return - fi - if [[ "${PPA:0:3}" == "deb" ]] ; then - juju-log "nova: 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 "nova: No PPA specified. Falling back to installation from Ubuntu archive." -} diff --git a/hooks/nova-compute-relations b/hooks/nova-compute-relations index 12499c4..b3d2ab9 100755 --- a/hooks/nova-compute-relations +++ b/hooks/nova-compute-relations @@ -1,99 +1,103 @@ -#!/bin/bash -FORMULA_DIR=$(dirname $0) +#!/bin/bash -e +CHARM_DIR=$(dirname $0) ARG0=${0##*/} -if [[ -e $FORMULA_DIR/nova-compute-common ]] ; then - . $FORMULA_DIR/nova-compute-common +if [[ -e $CHARM_DIR/nova-compute-common ]] ; then + . $CHARM_DIR/nova-compute-common else - echo "ERROR: Could not load nova-compute-common from $FORMULA_DIR" + juju-log "ERROR: Could not load nova-compute-common from $CHARM_DIR" fi function install_hook { - [[ -z $VIRT_TYPE ]] && VIRT_TYPE="kvm" - case $VIRT_TYPE in - "kvm") COMPUTE_PKG="nova-compute-kvm";; - "qemu") COMPUTE_PKG="nova-compute-qemu";; - "xen") COMPUTE_PKG="nova-compute-xen";; - "uml") COMPUTE_PKG="nova-compute-uml";; - "lxc") COMPUTE_PKG="nova-compute-lxc";; - *) juju-log "ERROR: Unsupported VIRT_TYPE=$VIRT_TYPE";; - esac + local virt_type=$(config-get virt-type) + local compute_pkg=$(determine_compute_package "$virt_type") apt-get -y install python-software-properties || exit 1 - add_ppa + configure_install_source $(config-get openstack-origin) apt-get update || exit 1 - apt-get -y install $COMPUTE_PKG nova-api nova-network || exit 1 - - # Configure any flags specified in deployment config - set_config_flags - - nova_ctl all stop + apt-get -y install $compute_pkg $PACKAGES || exit 1 + service_ctl all stop + set_or_update "auth_strategy" "keystone" } -function config_changed { +function config_changed() { + + # Determine whether or not we should do an upgrade, based on whether or not + # the version offered in openstack-origin is greater than what is installed. + + local install_src=$(config-get openstack-origin) + local cur=$(get_os_codename_package "nova-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 + set_config_flags - nova_ctl all restart + service_ctl all restart } function amqp_joined { - juju-log "amqp_joined: requesting credentials for $RABBIT_USER" - echo "amqp_joined: requesting credentials for $RABBIT_USER" - relation-set username=$RABBIT_USER - relation-set vhost=$RABBIT_VHOST + # we request a username on the rabbit queue + # and store it in nova.conf. our response is its IP + PASSWD + # but we configure that in _changed + local rabbit_user=$(config-get rabbit-user) + local rabbit_vhost=$(config-get rabbit-vhost) + juju-log "$CHARM - amqp_joined: requesting credentials for $rabbit_user" + relation-set username=$rabbit_user + relation-set vhost=$rabbit_vhost } function amqp_changed { - RABBIT_HOST=`relation-get private-address` - RABBIT_PASSWORD=`relation-get password` - if [[ -z $RABBIT_HOST ]] || [[ -z $RABBIT_PASSWORD ]] ; then - echo "amqp_changed: RABBIT_HOST||RABBIT_PASSWORD not set. Peer not ready? Exit 0 and retry" - exit 0 + # server creates our credentials and tells us where + # to connect. for now, using default vhost '/' + local rabbit_host=$(relation-get private-address) + local rabbit_password=$(relation-get password) + + if [[ -z $rabbit_host ]] || \ + [[ -z $rabbit_password ]] ; then + juju-log "$CHARM - amqp_changed: rabbit_host||rabbit_password not set." + exit 0 fi - echo "amqp_changed: Setting rabbit config in nova.conf: $RABBIT_HOST $RABBIT_USER $RABBIT_PASSWORD" - set_or_update rabbit_host $RABBIT_HOST - set_or_update rabbit_userid $RABBIT_USER - set_or_update rabbit_password $RABBIT_PASSWORD - set_or_update rabbit_virtual_host $RABBIT_VHOST - nova_ctl all restart + + local rabbit_user=$(config-get rabbit-user) + local rabbit_vhost=$(config-get rabbit-vhost) + juju-log "$CHARM - amqp_changed: Setting rabbit config in nova.conf: " \ + "$rabbit_user@$rabbit_host/$rabbit_vhost" + set_or_update rabbit_host $rabbit_host + set_or_update rabbit_userid $rabbit_user + set_or_update rabbit_password $rabbit_password + set_or_update rabbit_virtual_host $rabbit_vhost + service_ctl all restart } function db_joined { # tell mysql provider which database we want. it will create it and give us # credentials - juju-log "db_joined: requesting database access to $NOVA_DB for $DB_USER@`unit-get private-address`" - relation-set database=$NOVA_DB - relation-set username=$DB_USER - relation-set hostname=`unit-get private-address` + local nova_db=$(config-get nova-db) + local db_user=$(config-get db-user) + local hostname=$(unit-get private-address) + juju-log "$CHARM - db_joined: requesting database access to $nova_db for "\ + "$db_user@$hostname" + relation-set database=$nova_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" - exit 0 - fi - echo "db_changed: Configuring nova.conf for access to $NOVA_DB" - set_or_update sql_connection "mysql://$DB_USER:$DB_PASSWORD@$DB_HOST/$NOVA_DB" - nova_ctl all restart - # this works around lp #855971 until (ideally) we can add some functionality - # to nova/nova-manage to do this for us. reserve the IP of this host in the dhcp - # pool and assign it to this host - #DEFAULT_ETH=$(ip route | grep default | awk '{ print $5 }') - #IP=$(ifconfig $DEFAULT_ETH | grep 'inet addr' | awk '{ print $2 }' | cut -d: -f2) - #apt-get -y install mysql-client - #mysql -u $DB_USER -h $DB_HOST -p$DB_PASSWORD -e \ - # "UPDATE fixed_ips SET reserved='1', host='$(hostname)' \ - # WHERE address='$IP'" $NOVA_DB -} + local db_host=`relation-get private-address` + local db_password=`relation-get password` -function nova-network_changed { - MANAGER=`relation-get network_manager` - if [[ -z $MANAGER ]] ; then - echo "nova-network_changed: MANAGER not yet set. Exit 0 and retry" + if [[ -z $db_host ]] || [[ -z $db_password ]] ; then + juju-log "$CHARM - db_changed: db_host||db_password set, will retry." exit 0 fi - configure_network_manager $MANAGER - nova_ctl all restart + + local nova_db=$(config-get nova-db) + local db_user=$(config-get db-user) + juju-log "$CHARM - db_changed: Configuring nova.conf for access to $nova_db" + + set_or_update sql_connection "mysql://$db_user:$db_password@$db_host/$nova_db" + service_ctl all restart } function image-service_changed { @@ -103,20 +107,20 @@ function image-service_changed { exit 0 fi set_or_update glance_api_servers $GLANCE_API_SERVER - nova_ctl all restart + service_ctl all restart } -function keystone_joined { - # service=None lets keystone know we don't need anything entered - # into the service catalog. This hook exists to workaround lack - # of features explained here: - # https://lists.ubuntu.com/archives/juju/2012-March/001342.html - # Once landed, this type of reconfiguration should happen in a hook - # triggered by nova-cloud-controller's keystone relation. - apt-get -y install python-keystone - relation-set service="None" region="None" public_url="None" \ - admin_url="None" internal_url="None" - set_or_update "auth_strategy" "keystone" +function compute_changed { + # nova-c-c will inform us of the configured network manager. nova-compute + # needs to configure itself accordingly. + network_manager=`relation-get network_manager` + if [[ -n "$network_manager" ]] ; then + configure_network_manager "$network_manager" + fi + + # restart on all changed events. nova-c-c may send out a uuid to trigger + # remote restarts of services here (after db migrations, for instance) + service_ctl all restart } function ceph_joined { @@ -181,14 +185,12 @@ case $ARG0 in "amqp-relation-changed") amqp_changed ;; "shared-db-relation-joined") db_joined ;; "shared-db-relation-changed") db_changed ;; - "network-manager-relation-joined") exit 0 ;; - "network-manager-relation-changed") nova-network_changed ;; "image-service-relation-joined") exit 0 ;; "image-service-relation-changed") image-service_changed ;; "identity-service-relation-joined") keystone_joined ;; "identity-service-relation-changed") exit 0 ;; "ceph-relation-joined") ceph_joined;; "ceph-relation-changed") ceph_changed;; + "cloud-compute-relation-joined" ) exit 0 ;; + "cloud-compute-relation-changed") compute_changed ;; esac - - diff --git a/metadata.yaml b/metadata.yaml index d6a7b6d..ef7235b 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,4 +1,3 @@ -ensemble: formula name: nova-compute summary: "OpenStack compute" maintainer: Adam Gandelman @@ -14,11 +13,7 @@ requires: interface: mysql-shared amqp: interface: rabbitmq - identity-service: - interface: keystone image-service: interface: glance - network-manager: - interface: nova-network ceph: interface: ceph-client diff --git a/revision b/revision index fb1e7bc..ea70ce0 100644 --- a/revision +++ b/revision @@ -1 +1 @@ -54 +72