3
# Common utility functions used across all OpenStack charms.
6
juju-log "$CHARM ERROR: $@"
10
function service_ctl_status {
11
# Return 0 if a service is running, 1 otherwise.
13
local status=$(service $svc status | cut -d/ -f1 | awk '{ print $2 }')
17
*) error_out "Unexpected status of service $svc: $status" ;;
21
function service_ctl {
22
# control a specific service, or all (as defined by $SERVICES)
23
if [[ $1 == "all" ]] ; then
29
if [[ -z "$ctl" ]] || [[ -z "$action" ]] ; then
30
error_out "ERROR service_ctl: Not enough arguments"
36
service_ctl_status $i || service $i start ;;
38
service_ctl_status $i && service $i stop || return 0 ;;
40
service_ctl_status $i && service $i restart || service $i start ;;
42
if [[ $? != 0 ]] ; then
43
juju-log "$CHARM: service_ctl ERROR - Service $i failed to $action"
48
function configure_install_source {
49
# Setup and configure installation source based on a config flag.
52
# Default to installing from the main Ubuntu archive.
53
[[ $src == "distro" ]] || [[ -z "$src" ]] && return 0
57
# standard 'ppa:someppa/name' format.
58
if [[ "${src:0:4}" == "ppa:" ]] ; then
59
juju-log "$CHARM: Configuring installation from custom src ($src)"
60
add-apt-repository -y "$src" || error_out "Could not configure PPA access."
64
# standard 'deb http://url/ubuntu main' entries. gpg key ids must
65
# be appended to the end of url after a |, ie:
66
# 'deb http://url/ubuntu main|$GPGKEYID'
67
if [[ "${src:0:3}" == "deb" ]] ; then
68
juju-log "$CHARM: Configuring installation from custom src URL ($src)"
69
if echo "$src" | grep -q "|" ; then
70
# gpg key id tagged to end of url folloed by a |
71
url=$(echo $src | cut -d'|' -f1)
72
key=$(echo $src | cut -d'|' -f2)
73
juju-log "$CHARM: Importing repository key: $key"
74
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$key" || \
75
juju-log "$CHARM WARN: Could not import key from keyserver: $key"
77
juju-log "$CHARM No repository key specified."
80
echo "$url" > /etc/apt/sources.list.d/juju_deb.list
85
if [[ "${src:0:6}" == "cloud:" ]] ; then
86
local archive_key="5EDB1B62EC4926EA"
87
local rel=$(echo $src | cut -d: -f2)
88
local u_rel=$(echo $rel | cut -d- -f1)
89
local ca_rel=$(echo $rel | cut -d- -f2)
91
[[ "$u_rel" != "$DISTRIB_CODENAME" ]] &&
92
error_out "Cannot install from Cloud Archive pocket $src " \
93
"on this Ubuntu version ($DISTRIB_CODENAME)!"
95
# CA staging repos are standard PPAs.
96
if echo $ca_rel | grep -q "staging" ; then
97
ca_rel=$(echo $ca_rel | sed -e 's,/,-,g')
98
add-apt-repository -y ppa:ubuntu-cloud-archive/$ca_rel
102
# the others are LP-external deb repos.
104
"folsom"|"folsom/updates") pocket="precise-updates/folsom" ;;
105
"folsom/proposed") pocket="precise-proposed/folsom" ;;
106
*) error_out "Invalid Cloud Archive repo specified: $src"
109
entry="deb http://ubuntu-cloud.archive.canonical.com/ubuntu $pocket main"
111
>/etc/apt/sources.list.d/ubuntu-cloud-archive-$DISTRIB_CODENAME.list
112
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $archive_key
116
error_out "Invalid installation source specified in config: $src"
120
get_os_codename_install_source() {
121
# derive the openstack release provided by a supported installation source.
123
local codename="unknown"
126
# map ubuntu releases to the openstack version shipped with it.
127
if [[ "$rel" == "distro" ]] ; then
128
case "$DISTRIB_CODENAME" in
129
"oneiric") codename="diablo" ;;
130
"precise") codename="essex" ;;
131
"quantal") codename="folsom" ;;
132
"raring") codename="grizzly" ;;
136
# derive version from cloud archive strings.
137
if [[ "${rel:0:6}" == "cloud:" ]] ; then
138
rel=$(echo $rel | cut -d: -f2)
139
local u_rel=$(echo $rel | cut -d- -f1)
140
local ca_rel=$(echo $rel | cut -d- -f2)
141
if [[ "$u_rel" == "$DISTRIB_CODENAME" ]] ; then
143
"folsom"|"folsom/updates"|"folsom/proposed"|"folsom/staging")
145
"grizzly"|"grizzly/updates"|"grizzly/proposed"|"grizzly/staging")
146
codename="grizzly" ;;
151
# have a guess based on the deb string provided
152
if [[ "${rel:0:3}" == "deb" ]]; then
153
CODENAMES="diablo essex folsom grizzly"
154
for cname in $CODENAMES; do
155
if echo $rel | grep -q $cname; then
163
get_os_codename_package() {
164
local pkg_vers=$(dpkg -l | grep "$1" | awk '{ print $3 }') || echo "none"
165
case "${pkg_vers:0:6}" in
166
"2011.2") echo "diablo" ;;
167
"2012.1") echo "essex" ;;
168
"2012.2") echo "folsom" ;;
169
"2013.1") echo "grizzly" ;;
173
get_os_version_codename() {
175
"diablo") echo "2011.2" ;;
176
"essex") echo "2012.1" ;;
177
"folsom") echo "2012.2" ;;
178
"grizzly") echo "2012.3" ;;
183
dpkg -l | grep -q python-dnspython || {
184
apt-get -y install python-dnspython 2>&1 > /dev/null
191
# Test to see if already an IPv4 address
192
socket.inet_aton('$hostname')
196
answers = dns.resolver.query('$hostname', 'A')
198
print answers[0].address
199
except dns.resolver.NXDOMAIN:
204
# Common storage routines used by cinder, nova-volume and swift-storage.
206
# if configured to overwrite existing storage, we unmount the block-dev
207
# if mounted and clear any previous pv signatures
209
juju-log "Cleaining storage '$block_dev'"
210
if grep -q "^$block_dev" /proc/mounts ; then
211
mp=$(grep "^$block_dev" /proc/mounts | awk '{ print $2 }')
212
juju-log "Unmounting $block_dev from $mp"
213
umount "$mp" || error_out "ERROR: Could not unmount storage from $mp"
215
if pvdisplay "$block_dev" >/dev/null 2>&1 ; then
216
juju-log "Removing existing LVM PV signatures from $block_dev"
218
# deactivate any volgroups that may be built on this dev
219
vg=$(pvdisplay $block_dev | grep "VG Name" | awk '{ print $3 }')
220
if [[ -n "$vg" ]] ; then
221
juju-log "Deactivating existing volume group: $vg"
222
vgchange -an "$vg" ||
223
error_out "ERROR: Could not deactivate volgroup $vg. Is it in use?"
225
echo "yes" | pvremove -ff "$block_dev" ||
226
error_out "Could not pvremove $block_dev"
228
juju-log "Zapping disk of all GPT and MBR structures"
229
sgdisk --zap-all $block_dev ||
230
error_out "Unable to zap $block_dev"
234
function get_block_device() {
235
# given a string, return full path to the block device for that
236
# if input is not a block device, find a loopback device
240
/dev/*) [[ ! -b "$input" ]] && error_out "$input does not exist."
241
echo "$input"; return 0;;
243
*) [[ ! -b "/dev/$input" ]] && error_out "/dev/$input does not exist."
244
echo "/dev/$input"; return 0;;
247
# this represents a file
248
# support "/path/to/file|5G"
249
local fpath size oifs="$IFS"
250
if [ "${input#*|}" != "${input}" ]; then
258
## loop devices are not namespaced. This is bad for containers.
259
## it means that the output of 'losetup' may have the given $fpath
260
## in it, but that may not represent this containers $fpath, but
261
## another containers. To address that, we really need to
262
## allow some uniq container-id to be expanded within path.
263
## TODO: find a unique container-id that will be consistent for
264
## this container throughout its lifetime and expand it
266
# fpath=${fpath//%{id}/$THAT_ID}
269
# parse through 'losetup -a' output, looking for this file
270
# output is expected to look like:
271
# /dev/loop0: [0807]:961814 (/tmp/my.img)
273
awk 'BEGIN { found=0; }
274
$3 == f { sub(/:$/,"",$1); print $1; found=found+1; }
275
END { if( found == 0 || found == 1 ) { exit(0); }; exit(1); }' \
278
if [ $? -ne 0 ]; then
279
echo "multiple devices found for $fpath: $found" 1>&2
283
[ -n "$found" -a -b "$found" ] && { echo "$found"; return 1; }
285
if [ -n "$found" ]; then
286
echo "confused, $found is not a block device for $fpath";
290
# no existing device was found, create one
291
mkdir -p "${fpath%/*}"
292
truncate --size "$size" "$fpath" ||
293
{ echo "failed to create $fpath of size $size"; return 1; }
295
found=$(losetup --find --show "$fpath") ||
296
{ echo "failed to setup loop device for $fpath" 1>&2; return 1; }