blob: b94e134c0f2253bc96b0a6e8f0fa9e598917a98e [file] [log] [blame]
Sean Daguee263c822014-12-05 14:25:28 -05001#!/bin/bash
2#
Dean Troyerdff49a22014-01-30 15:37:40 -06003# functions-common - Common functions used by DevStack components
4#
5# The canonical copy of this file is maintained in the DevStack repo.
6# All modifications should be made there and then sync'ed to other repos
7# as required.
8#
9# This file is sorted alphabetically within the function groups.
10#
11# - Config Functions
12# - Control Functions
13# - Distro Functions
14# - Git Functions
15# - OpenStack Functions
16# - Package Functions
17# - Process Functions
Dean Troyerdff49a22014-01-30 15:37:40 -060018# - Service Functions
Masayuki Igawaf6368d32014-02-20 13:31:26 +090019# - System Functions
Dean Troyerdff49a22014-01-30 15:37:40 -060020#
21# The following variables are assumed to be defined by certain functions:
22#
23# - ``ENABLED_SERVICES``
24# - ``ERROR_ON_CLONE``
25# - ``FILES``
26# - ``OFFLINE``
Dean Troyerdff49a22014-01-30 15:37:40 -060027# - ``RECLONE``
Masayuki Igawad20f6322014-02-28 09:22:37 +090028# - ``REQUIREMENTS_DIR``
29# - ``STACK_USER``
Dean Troyerdff49a22014-01-30 15:37:40 -060030# - ``TRACK_DEPENDS``
Masayuki Igawad20f6322014-02-28 09:22:37 +090031# - ``UNDO_REQUIREMENTS``
Dean Troyerdff49a22014-01-30 15:37:40 -060032# - ``http_proxy``, ``https_proxy``, ``no_proxy``
Dean Troyer3324f192014-09-18 09:26:39 -050033#
Dean Troyerdff49a22014-01-30 15:37:40 -060034
35# Save trace setting
36XTRACE=$(set +o | grep xtrace)
37set +o xtrace
38
Sean Daguecc524062014-10-01 09:06:43 -040039# Global Config Variables
40declare -A GITREPO
41declare -A GITBRANCH
42declare -A GITDIR
43
Sean Dague53753292014-12-04 19:38:15 -050044TRACK_DEPENDS=${TRACK_DEPENDS:-False}
45
Dean Troyerdff49a22014-01-30 15:37:40 -060046
47# Normalize config values to True or False
48# Accepts as False: 0 no No NO false False FALSE
49# Accepts as True: 1 yes Yes YES true True TRUE
50# VAR=$(trueorfalse default-value test-value)
Ian Wienandaee18c72014-02-21 15:35:08 +110051function trueorfalse {
Sean Dague45917cc2014-02-24 16:09:14 -050052 local xtrace=$(set +o | grep xtrace)
53 set +o xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -060054 local default=$1
Sean Dague53753292014-12-04 19:38:15 -050055 local literal=$2
Dean Troyera1b82cc2015-01-30 13:54:40 -060056 local testval=${!literal:-}
Dean Troyerdff49a22014-01-30 15:37:40 -060057
58 [[ -z "$testval" ]] && { echo "$default"; return; }
59 [[ "0 no No NO false False FALSE" =~ "$testval" ]] && { echo "False"; return; }
60 [[ "1 yes Yes YES true True TRUE" =~ "$testval" ]] && { echo "True"; return; }
61 echo "$default"
Sean Dague45917cc2014-02-24 16:09:14 -050062 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -060063}
64
65
66# Control Functions
67# =================
68
69# Prints backtrace info
70# filename:lineno:function
71# backtrace level
72function backtrace {
73 local level=$1
74 local deep=$((${#BASH_SOURCE[@]} - 1))
75 echo "[Call Trace]"
76 while [ $level -le $deep ]; do
77 echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
78 deep=$((deep - 1))
79 done
80}
81
82# Prints line number and "message" then exits
83# die $LINENO "message"
Ian Wienandaee18c72014-02-21 15:35:08 +110084function die {
Dean Troyerdff49a22014-01-30 15:37:40 -060085 local exitcode=$?
86 set +o xtrace
87 local line=$1; shift
88 if [ $exitcode == 0 ]; then
89 exitcode=1
90 fi
91 backtrace 2
92 err $line "$*"
Dean Troyera25a6f62014-02-24 16:03:41 -060093 # Give buffers a second to flush
94 sleep 1
Dean Troyerdff49a22014-01-30 15:37:40 -060095 exit $exitcode
96}
97
98# Checks an environment variable is not set or has length 0 OR if the
99# exit code is non-zero and prints "message" and exits
100# NOTE: env-var is the variable name without a '$'
101# die_if_not_set $LINENO env-var "message"
Ian Wienandaee18c72014-02-21 15:35:08 +1100102function die_if_not_set {
Dean Troyerdff49a22014-01-30 15:37:40 -0600103 local exitcode=$?
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500104 local xtrace=$(set +o | grep xtrace)
Dean Troyerdff49a22014-01-30 15:37:40 -0600105 set +o xtrace
106 local line=$1; shift
107 local evar=$1; shift
108 if ! is_set $evar || [ $exitcode != 0 ]; then
109 die $line "$*"
110 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500111 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -0600112}
113
114# Prints line number and "message" in error format
115# err $LINENO "message"
Ian Wienandaee18c72014-02-21 15:35:08 +1100116function err {
Dean Troyerdff49a22014-01-30 15:37:40 -0600117 local exitcode=$?
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500118 local xtrace=$(set +o | grep xtrace)
Dean Troyerdff49a22014-01-30 15:37:40 -0600119 set +o xtrace
120 local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
121 echo $msg 1>&2;
Dean Troyerdde41d02014-12-09 17:47:57 -0600122 if [[ -n ${LOGDIR} ]]; then
123 echo $msg >> "${LOGDIR}/error.log"
Dean Troyerdff49a22014-01-30 15:37:40 -0600124 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500125 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -0600126 return $exitcode
127}
128
129# Checks an environment variable is not set or has length 0 OR if the
130# exit code is non-zero and prints "message"
131# NOTE: env-var is the variable name without a '$'
132# err_if_not_set $LINENO env-var "message"
Ian Wienandaee18c72014-02-21 15:35:08 +1100133function err_if_not_set {
Dean Troyerdff49a22014-01-30 15:37:40 -0600134 local exitcode=$?
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500135 local xtrace=$(set +o | grep xtrace)
Dean Troyerdff49a22014-01-30 15:37:40 -0600136 set +o xtrace
137 local line=$1; shift
138 local evar=$1; shift
139 if ! is_set $evar || [ $exitcode != 0 ]; then
140 err $line "$*"
141 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500142 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -0600143 return $exitcode
144}
145
146# Exit after outputting a message about the distribution not being supported.
147# exit_distro_not_supported [optional-string-telling-what-is-missing]
148function exit_distro_not_supported {
149 if [[ -z "$DISTRO" ]]; then
150 GetDistro
151 fi
152
153 if [ $# -gt 0 ]; then
154 die $LINENO "Support for $DISTRO is incomplete: no support for $@"
155 else
156 die $LINENO "Support for $DISTRO is incomplete."
157 fi
158}
159
160# Test if the named environment variable is set and not zero length
161# is_set env-var
Ian Wienandaee18c72014-02-21 15:35:08 +1100162function is_set {
Dean Troyerdff49a22014-01-30 15:37:40 -0600163 local var=\$"$1"
164 eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
165}
166
167# Prints line number and "message" in warning format
168# warn $LINENO "message"
Ian Wienandaee18c72014-02-21 15:35:08 +1100169function warn {
Dean Troyerdff49a22014-01-30 15:37:40 -0600170 local exitcode=$?
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500171 local xtrace=$(set +o | grep xtrace)
Dean Troyerdff49a22014-01-30 15:37:40 -0600172 set +o xtrace
173 local msg="[WARNING] ${BASH_SOURCE[2]}:$1 $2"
174 echo $msg 1>&2;
Dean Troyerdde41d02014-12-09 17:47:57 -0600175 if [[ -n ${LOGDIR} ]]; then
176 echo $msg >> "${LOGDIR}/error.log"
Dean Troyerdff49a22014-01-30 15:37:40 -0600177 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500178 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -0600179 return $exitcode
180}
181
182
183# Distro Functions
184# ================
185
186# Determine OS Vendor, Release and Update
187# Tested with OS/X, Ubuntu, RedHat, CentOS, Fedora
188# Returns results in global variables:
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500189# ``os_VENDOR`` - vendor name: ``Ubuntu``, ``Fedora``, etc
190# ``os_RELEASE`` - major release: ``14.04`` (Ubuntu), ``20`` (Fedora)
191# ``os_UPDATE`` - update: ex. the ``5`` in ``RHEL6.5``
192# ``os_PACKAGE`` - package type: ``deb`` or ``rpm``
193# ``os_CODENAME`` - vendor's codename for release: ``snow leopard``, ``trusty``
Sean Dague53753292014-12-04 19:38:15 -0500194os_VENDOR=""
195os_RELEASE=""
196os_UPDATE=""
197os_PACKAGE=""
198os_CODENAME=""
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500199
Dean Troyerdff49a22014-01-30 15:37:40 -0600200# GetOSVersion
Ian Wienandaee18c72014-02-21 15:35:08 +1100201function GetOSVersion {
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500202
Dean Troyerdff49a22014-01-30 15:37:40 -0600203 # Figure out which vendor we are
204 if [[ -x "`which sw_vers 2>/dev/null`" ]]; then
205 # OS/X
206 os_VENDOR=`sw_vers -productName`
207 os_RELEASE=`sw_vers -productVersion`
208 os_UPDATE=${os_RELEASE##*.}
209 os_RELEASE=${os_RELEASE%.*}
210 os_PACKAGE=""
211 if [[ "$os_RELEASE" =~ "10.7" ]]; then
212 os_CODENAME="lion"
213 elif [[ "$os_RELEASE" =~ "10.6" ]]; then
214 os_CODENAME="snow leopard"
215 elif [[ "$os_RELEASE" =~ "10.5" ]]; then
216 os_CODENAME="leopard"
217 elif [[ "$os_RELEASE" =~ "10.4" ]]; then
218 os_CODENAME="tiger"
219 elif [[ "$os_RELEASE" =~ "10.3" ]]; then
220 os_CODENAME="panther"
221 else
222 os_CODENAME=""
223 fi
224 elif [[ -x $(which lsb_release 2>/dev/null) ]]; then
225 os_VENDOR=$(lsb_release -i -s)
226 os_RELEASE=$(lsb_release -r -s)
227 os_UPDATE=""
228 os_PACKAGE="rpm"
229 if [[ "Debian,Ubuntu,LinuxMint" =~ $os_VENDOR ]]; then
230 os_PACKAGE="deb"
231 elif [[ "SUSE LINUX" =~ $os_VENDOR ]]; then
232 lsb_release -d -s | grep -q openSUSE
233 if [[ $? -eq 0 ]]; then
234 os_VENDOR="openSUSE"
235 fi
236 elif [[ $os_VENDOR == "openSUSE project" ]]; then
237 os_VENDOR="openSUSE"
238 elif [[ $os_VENDOR =~ Red.*Hat ]]; then
239 os_VENDOR="Red Hat"
240 fi
241 os_CODENAME=$(lsb_release -c -s)
242 elif [[ -r /etc/redhat-release ]]; then
243 # Red Hat Enterprise Linux Server release 5.5 (Tikanga)
244 # Red Hat Enterprise Linux Server release 7.0 Beta (Maipo)
245 # CentOS release 5.5 (Final)
246 # CentOS Linux release 6.0 (Final)
247 # Fedora release 16 (Verne)
248 # XenServer release 6.2.0-70446c (xenenterprise)
249 os_CODENAME=""
250 for r in "Red Hat" CentOS Fedora XenServer; do
251 os_VENDOR=$r
252 if [[ -n "`grep \"$r\" /etc/redhat-release`" ]]; then
253 ver=`sed -e 's/^.* \([0-9].*\) (\(.*\)).*$/\1\|\2/' /etc/redhat-release`
254 os_CODENAME=${ver#*|}
255 os_RELEASE=${ver%|*}
256 os_UPDATE=${os_RELEASE##*.}
257 os_RELEASE=${os_RELEASE%.*}
258 break
259 fi
260 os_VENDOR=""
261 done
262 os_PACKAGE="rpm"
263 elif [[ -r /etc/SuSE-release ]]; then
264 for r in openSUSE "SUSE Linux"; do
265 if [[ "$r" = "SUSE Linux" ]]; then
266 os_VENDOR="SUSE LINUX"
267 else
268 os_VENDOR=$r
269 fi
270
271 if [[ -n "`grep \"$r\" /etc/SuSE-release`" ]]; then
272 os_CODENAME=`grep "CODENAME = " /etc/SuSE-release | sed 's:.* = ::g'`
273 os_RELEASE=`grep "VERSION = " /etc/SuSE-release | sed 's:.* = ::g'`
274 os_UPDATE=`grep "PATCHLEVEL = " /etc/SuSE-release | sed 's:.* = ::g'`
275 break
276 fi
277 os_VENDOR=""
278 done
279 os_PACKAGE="rpm"
280 # If lsb_release is not installed, we should be able to detect Debian OS
281 elif [[ -f /etc/debian_version ]] && [[ $(cat /proc/version) =~ "Debian" ]]; then
282 os_VENDOR="Debian"
283 os_PACKAGE="deb"
284 os_CODENAME=$(awk '/VERSION=/' /etc/os-release | sed 's/VERSION=//' | sed -r 's/\"|\(|\)//g' | awk '{print $2}')
285 os_RELEASE=$(awk '/VERSION_ID=/' /etc/os-release | sed 's/VERSION_ID=//' | sed 's/\"//g')
286 fi
287 export os_VENDOR os_RELEASE os_UPDATE os_PACKAGE os_CODENAME
288}
289
290# Translate the OS version values into common nomenclature
291# Sets global ``DISTRO`` from the ``os_*`` values
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500292declare DISTRO
293
Ian Wienandaee18c72014-02-21 15:35:08 +1100294function GetDistro {
Dean Troyerdff49a22014-01-30 15:37:40 -0600295 GetOSVersion
296 if [[ "$os_VENDOR" =~ (Ubuntu) || "$os_VENDOR" =~ (Debian) ]]; then
297 # 'Everyone' refers to Ubuntu / Debian releases by the code name adjective
298 DISTRO=$os_CODENAME
299 elif [[ "$os_VENDOR" =~ (Fedora) ]]; then
300 # For Fedora, just use 'f' and the release
301 DISTRO="f$os_RELEASE"
302 elif [[ "$os_VENDOR" =~ (openSUSE) ]]; then
303 DISTRO="opensuse-$os_RELEASE"
304 elif [[ "$os_VENDOR" =~ (SUSE LINUX) ]]; then
305 # For SLE, also use the service pack
306 if [[ -z "$os_UPDATE" ]]; then
307 DISTRO="sle${os_RELEASE}"
308 else
309 DISTRO="sle${os_RELEASE}sp${os_UPDATE}"
310 fi
anju Tiwari6c639c92014-07-15 18:11:54 +0530311 elif [[ "$os_VENDOR" =~ (Red Hat) || \
312 "$os_VENDOR" =~ (CentOS) || \
313 "$os_VENDOR" =~ (OracleServer) ]]; then
Dean Troyerdff49a22014-01-30 15:37:40 -0600314 # Drop the . release as we assume it's compatible
315 DISTRO="rhel${os_RELEASE::1}"
316 elif [[ "$os_VENDOR" =~ (XenServer) ]]; then
317 DISTRO="xs$os_RELEASE"
318 else
319 # Catch-all for now is Vendor + Release + Update
320 DISTRO="$os_VENDOR-$os_RELEASE.$os_UPDATE"
321 fi
322 export DISTRO
323}
324
325# Utility function for checking machine architecture
326# is_arch arch-type
327function is_arch {
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500328 [[ "$(uname -m)" == "$1" ]]
Dean Troyerdff49a22014-01-30 15:37:40 -0600329}
330
331# Determine if current distribution is a Fedora-based distribution
332# (Fedora, RHEL, CentOS, etc).
333# is_fedora
334function is_fedora {
335 if [[ -z "$os_VENDOR" ]]; then
336 GetOSVersion
337 fi
338
anju Tiwari6c639c92014-07-15 18:11:54 +0530339 [ "$os_VENDOR" = "Fedora" ] || [ "$os_VENDOR" = "Red Hat" ] || \
340 [ "$os_VENDOR" = "CentOS" ] || [ "$os_VENDOR" = "OracleServer" ]
Dean Troyerdff49a22014-01-30 15:37:40 -0600341}
342
343
344# Determine if current distribution is a SUSE-based distribution
345# (openSUSE, SLE).
346# is_suse
347function is_suse {
348 if [[ -z "$os_VENDOR" ]]; then
349 GetOSVersion
350 fi
351
352 [ "$os_VENDOR" = "openSUSE" ] || [ "$os_VENDOR" = "SUSE LINUX" ]
353}
354
355
356# Determine if current distribution is an Ubuntu-based distribution
357# It will also detect non-Ubuntu but Debian-based distros
358# is_ubuntu
359function is_ubuntu {
360 if [[ -z "$os_PACKAGE" ]]; then
361 GetOSVersion
362 fi
363 [ "$os_PACKAGE" = "deb" ]
364}
365
366
367# Git Functions
368# =============
369
Dean Troyerabc7b1d2014-02-12 12:09:22 -0600370# Returns openstack release name for a given branch name
371# ``get_release_name_from_branch branch-name``
Ian Wienandaee18c72014-02-21 15:35:08 +1100372function get_release_name_from_branch {
Dean Troyerabc7b1d2014-02-12 12:09:22 -0600373 local branch=$1
Adam Gandelman8f385722014-10-14 15:50:18 -0700374 if [[ $branch =~ "stable/" || $branch =~ "proposed/" ]]; then
Dean Troyerabc7b1d2014-02-12 12:09:22 -0600375 echo ${branch#*/}
376 else
377 echo "master"
378 fi
379}
380
Dean Troyerdff49a22014-01-30 15:37:40 -0600381# git clone only if directory doesn't exist already. Since ``DEST`` might not
382# be owned by the installation user, we create the directory and change the
383# ownership to the proper user.
Dean Troyer50cda692014-07-25 11:57:20 -0500384# Set global ``RECLONE=yes`` to simulate a clone when dest-dir exists
385# Set global ``ERROR_ON_CLONE=True`` to abort execution with an error if the git repo
Dean Troyerdff49a22014-01-30 15:37:40 -0600386# does not exist (default is False, meaning the repo will be cloned).
Sean Dague53753292014-12-04 19:38:15 -0500387# Uses globals ``ERROR_ON_CLONE``, ``OFFLINE``, ``RECLONE``
Dean Troyerdff49a22014-01-30 15:37:40 -0600388# git_clone remote dest-dir branch
389function git_clone {
Dean Troyer50cda692014-07-25 11:57:20 -0500390 local git_remote=$1
391 local git_dest=$2
392 local git_ref=$3
393 local orig_dir=$(pwd)
Jamie Lennox51f0de52014-10-20 16:32:34 +0200394 local git_clone_flags=""
Dean Troyer50cda692014-07-25 11:57:20 -0500395
Sean Dague53753292014-12-04 19:38:15 -0500396 RECLONE=$(trueorfalse False RECLONE)
Kevin Benton59d52f32015-01-17 11:29:12 -0800397 if [[ "${GIT_DEPTH}" -gt 0 ]]; then
Jamie Lennox51f0de52014-10-20 16:32:34 +0200398 git_clone_flags="$git_clone_flags --depth $GIT_DEPTH"
399 fi
400
Dean Troyerdff49a22014-01-30 15:37:40 -0600401 if [[ "$OFFLINE" = "True" ]]; then
402 echo "Running in offline mode, clones already exist"
403 # print out the results so we know what change was used in the logs
Dean Troyer50cda692014-07-25 11:57:20 -0500404 cd $git_dest
Dean Troyerdff49a22014-01-30 15:37:40 -0600405 git show --oneline | head -1
Sean Dague64bd0162014-03-12 13:04:22 -0400406 cd $orig_dir
Dean Troyerdff49a22014-01-30 15:37:40 -0600407 return
408 fi
409
Dean Troyer50cda692014-07-25 11:57:20 -0500410 if echo $git_ref | egrep -q "^refs"; then
Dean Troyerdff49a22014-01-30 15:37:40 -0600411 # If our branch name is a gerrit style refs/changes/...
Dean Troyer50cda692014-07-25 11:57:20 -0500412 if [[ ! -d $git_dest ]]; then
Dean Troyerdff49a22014-01-30 15:37:40 -0600413 [[ "$ERROR_ON_CLONE" = "True" ]] && \
414 die $LINENO "Cloning not allowed in this configuration"
Jamie Lennox51f0de52014-10-20 16:32:34 +0200415 git_timed clone $git_clone_flags $git_remote $git_dest
Dean Troyerdff49a22014-01-30 15:37:40 -0600416 fi
Dean Troyer50cda692014-07-25 11:57:20 -0500417 cd $git_dest
418 git_timed fetch $git_remote $git_ref && git checkout FETCH_HEAD
Dean Troyerdff49a22014-01-30 15:37:40 -0600419 else
420 # do a full clone only if the directory doesn't exist
Dean Troyer50cda692014-07-25 11:57:20 -0500421 if [[ ! -d $git_dest ]]; then
Dean Troyerdff49a22014-01-30 15:37:40 -0600422 [[ "$ERROR_ON_CLONE" = "True" ]] && \
423 die $LINENO "Cloning not allowed in this configuration"
Jamie Lennox51f0de52014-10-20 16:32:34 +0200424 git_timed clone $git_clone_flags $git_remote $git_dest
Dean Troyer50cda692014-07-25 11:57:20 -0500425 cd $git_dest
Dean Troyerdff49a22014-01-30 15:37:40 -0600426 # This checkout syntax works for both branches and tags
Dean Troyer50cda692014-07-25 11:57:20 -0500427 git checkout $git_ref
Dean Troyerdff49a22014-01-30 15:37:40 -0600428 elif [[ "$RECLONE" = "True" ]]; then
429 # if it does exist then simulate what clone does if asked to RECLONE
Dean Troyer50cda692014-07-25 11:57:20 -0500430 cd $git_dest
Dean Troyerdff49a22014-01-30 15:37:40 -0600431 # set the url to pull from and fetch
Dean Troyer50cda692014-07-25 11:57:20 -0500432 git remote set-url origin $git_remote
Ian Wienandd53ad0b2014-02-20 13:55:13 +1100433 git_timed fetch origin
Dean Troyerdff49a22014-01-30 15:37:40 -0600434 # remove the existing ignored files (like pyc) as they cause breakage
435 # (due to the py files having older timestamps than our pyc, so python
436 # thinks the pyc files are correct using them)
Dean Troyer50cda692014-07-25 11:57:20 -0500437 find $git_dest -name '*.pyc' -delete
Dean Troyerdff49a22014-01-30 15:37:40 -0600438
Dean Troyer50cda692014-07-25 11:57:20 -0500439 # handle git_ref accordingly to type (tag, branch)
440 if [[ -n "`git show-ref refs/tags/$git_ref`" ]]; then
441 git_update_tag $git_ref
442 elif [[ -n "`git show-ref refs/heads/$git_ref`" ]]; then
443 git_update_branch $git_ref
444 elif [[ -n "`git show-ref refs/remotes/origin/$git_ref`" ]]; then
445 git_update_remote_branch $git_ref
Dean Troyerdff49a22014-01-30 15:37:40 -0600446 else
Dean Troyer50cda692014-07-25 11:57:20 -0500447 die $LINENO "$git_ref is neither branch nor tag"
Dean Troyerdff49a22014-01-30 15:37:40 -0600448 fi
449
450 fi
451 fi
452
453 # print out the results so we know what change was used in the logs
Dean Troyer50cda692014-07-25 11:57:20 -0500454 cd $git_dest
Dean Troyerdff49a22014-01-30 15:37:40 -0600455 git show --oneline | head -1
Sean Dague64bd0162014-03-12 13:04:22 -0400456 cd $orig_dir
Dean Troyerdff49a22014-01-30 15:37:40 -0600457}
458
Sean Daguecc524062014-10-01 09:06:43 -0400459# A variation on git clone that lets us specify a project by it's
460# actual name, like oslo.config. This is exceptionally useful in the
461# library installation case
462function git_clone_by_name {
463 local name=$1
464 local repo=${GITREPO[$name]}
465 local dir=${GITDIR[$name]}
466 local branch=${GITBRANCH[$name]}
467 git_clone $repo $dir $branch
468}
469
470
Ian Wienandd53ad0b2014-02-20 13:55:13 +1100471# git can sometimes get itself infinitely stuck with transient network
472# errors or other issues with the remote end. This wraps git in a
473# timeout/retry loop and is intended to watch over non-local git
474# processes that might hang. GIT_TIMEOUT, if set, is passed directly
475# to timeout(1); otherwise the default value of 0 maintains the status
476# quo of waiting forever.
477# usage: git_timed <git-command>
Ian Wienandaee18c72014-02-21 15:35:08 +1100478function git_timed {
Ian Wienandd53ad0b2014-02-20 13:55:13 +1100479 local count=0
480 local timeout=0
481
482 if [[ -n "${GIT_TIMEOUT}" ]]; then
483 timeout=${GIT_TIMEOUT}
484 fi
485
486 until timeout -s SIGINT ${timeout} git "$@"; do
487 # 124 is timeout(1)'s special return code when it reached the
488 # timeout; otherwise assume fatal failure
489 if [[ $? -ne 124 ]]; then
490 die $LINENO "git call failed: [git $@]"
491 fi
492
493 count=$(($count + 1))
494 warn "timeout ${count} for git call: [git $@]"
495 if [ $count -eq 3 ]; then
496 die $LINENO "Maximum of 3 git retries reached"
497 fi
498 sleep 5
499 done
500}
501
Dean Troyerdff49a22014-01-30 15:37:40 -0600502# git update using reference as a branch.
503# git_update_branch ref
Ian Wienandaee18c72014-02-21 15:35:08 +1100504function git_update_branch {
Dean Troyer50cda692014-07-25 11:57:20 -0500505 local git_branch=$1
Dean Troyerdff49a22014-01-30 15:37:40 -0600506
Dean Troyer50cda692014-07-25 11:57:20 -0500507 git checkout -f origin/$git_branch
Dean Troyerdff49a22014-01-30 15:37:40 -0600508 # a local branch might not exist
Dean Troyer50cda692014-07-25 11:57:20 -0500509 git branch -D $git_branch || true
510 git checkout -b $git_branch
Dean Troyerdff49a22014-01-30 15:37:40 -0600511}
512
513# git update using reference as a branch.
514# git_update_remote_branch ref
Ian Wienandaee18c72014-02-21 15:35:08 +1100515function git_update_remote_branch {
Dean Troyer50cda692014-07-25 11:57:20 -0500516 local git_branch=$1
Dean Troyerdff49a22014-01-30 15:37:40 -0600517
Dean Troyer50cda692014-07-25 11:57:20 -0500518 git checkout -b $git_branch -t origin/$git_branch
Dean Troyerdff49a22014-01-30 15:37:40 -0600519}
520
521# git update using reference as a tag. Be careful editing source at that repo
522# as working copy will be in a detached mode
523# git_update_tag ref
Ian Wienandaee18c72014-02-21 15:35:08 +1100524function git_update_tag {
Dean Troyer50cda692014-07-25 11:57:20 -0500525 local git_tag=$1
Dean Troyerdff49a22014-01-30 15:37:40 -0600526
Dean Troyer50cda692014-07-25 11:57:20 -0500527 git tag -d $git_tag
Dean Troyerdff49a22014-01-30 15:37:40 -0600528 # fetching given tag only
Dean Troyer50cda692014-07-25 11:57:20 -0500529 git_timed fetch origin tag $git_tag
530 git checkout -f $git_tag
Dean Troyerdff49a22014-01-30 15:37:40 -0600531}
532
533
534# OpenStack Functions
535# ===================
536
537# Get the default value for HOST_IP
538# get_default_host_ip fixed_range floating_range host_ip_iface host_ip
Ian Wienandaee18c72014-02-21 15:35:08 +1100539function get_default_host_ip {
Dean Troyerdff49a22014-01-30 15:37:40 -0600540 local fixed_range=$1
541 local floating_range=$2
542 local host_ip_iface=$3
543 local host_ip=$4
544
Dean Troyerdff49a22014-01-30 15:37:40 -0600545 # Search for an IP unless an explicit is set by ``HOST_IP`` environment variable
546 if [ -z "$host_ip" -o "$host_ip" == "dhcp" ]; then
547 host_ip=""
Andreas Scheuringa3430272015-03-09 16:55:32 +0100548 # Find the interface used for the default route
549 host_ip_iface=${host_ip_iface:-$(ip route | awk '/default/ {print $5}' | head -1)}
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500550 local host_ips=$(LC_ALL=C ip -f inet addr show ${host_ip_iface} | awk '/inet/ {split($2,parts,"/"); print parts[1]}')
551 local ip
552 for ip in $host_ips; do
Dean Troyerdff49a22014-01-30 15:37:40 -0600553 # Attempt to filter out IP addresses that are part of the fixed and
554 # floating range. Note that this method only works if the ``netaddr``
555 # python library is installed. If it is not installed, an error
556 # will be printed and the first IP from the interface will be used.
557 # If that is not correct set ``HOST_IP`` in ``localrc`` to the correct
558 # address.
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500559 if ! (address_in_net $ip $fixed_range || address_in_net $ip $floating_range); then
560 host_ip=$ip
Dean Troyerdff49a22014-01-30 15:37:40 -0600561 break;
562 fi
563 done
564 fi
565 echo $host_ip
566}
567
Attila Fazekasf71b5002014-05-28 09:52:22 +0200568# Generates hex string from ``size`` byte of pseudo random data
569# generate_hex_string size
570function generate_hex_string {
571 local size=$1
572 hexdump -n "$size" -v -e '/1 "%02x"' /dev/urandom
573}
574
Dean Troyerdff49a22014-01-30 15:37:40 -0600575# Grab a numbered field from python prettytable output
576# Fields are numbered starting with 1
577# Reverse syntax is supported: -1 is the last field, -2 is second to last, etc.
578# get_field field-number
Ian Wienandaee18c72014-02-21 15:35:08 +1100579function get_field {
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500580 local data field
Dean Troyerdff49a22014-01-30 15:37:40 -0600581 while read data; do
582 if [ "$1" -lt 0 ]; then
583 field="(\$(NF$1))"
584 else
585 field="\$$(($1 + 1))"
586 fi
587 echo "$data" | awk -F'[ \t]*\\|[ \t]*' "{print $field}"
588 done
589}
590
yuntongjinf26deea2015-02-28 10:50:34 +0800591# install default policy
592# copy over a default policy.json and policy.d for projects
593function install_default_policy {
594 local project=$1
595 local project_uc=$(echo $1|tr a-z A-Z)
596 local conf_dir="${project_uc}_CONF_DIR"
597 # eval conf dir to get the variable
598 conf_dir="${!conf_dir}"
599 local project_dir="${project_uc}_DIR"
600 # eval project dir to get the variable
601 project_dir="${!project_dir}"
602 local sample_conf_dir="${project_dir}/etc/${project}"
603 local sample_policy_dir="${project_dir}/etc/${project}/policy.d"
604
605 # first copy any policy.json
606 cp -p $sample_conf_dir/policy.json $conf_dir
607 # then optionally copy over policy.d
608 if [[ -d $sample_policy_dir ]]; then
609 cp -r $sample_policy_dir $conf_dir/policy.d
610 fi
611}
612
Dean Troyerdff49a22014-01-30 15:37:40 -0600613# Add a policy to a policy.json file
614# Do nothing if the policy already exists
615# ``policy_add policy_file policy_name policy_permissions``
Ian Wienandaee18c72014-02-21 15:35:08 +1100616function policy_add {
Dean Troyerdff49a22014-01-30 15:37:40 -0600617 local policy_file=$1
618 local policy_name=$2
619 local policy_perm=$3
620
621 if grep -q ${policy_name} ${policy_file}; then
622 echo "Policy ${policy_name} already exists in ${policy_file}"
623 return
624 fi
625
626 # Add a terminating comma to policy lines without one
627 # Remove the closing '}' and all lines following to the end-of-file
628 local tmpfile=$(mktemp)
629 uniq ${policy_file} | sed -e '
630 s/]$/],/
631 /^[}]/,$d
632 ' > ${tmpfile}
633
634 # Append policy and closing brace
635 echo " \"${policy_name}\": ${policy_perm}" >>${tmpfile}
636 echo "}" >>${tmpfile}
637
638 mv ${tmpfile} ${policy_file}
639}
640
Alistair Coles24779f62014-10-15 18:57:59 +0100641# Gets or creates a domain
642# Usage: get_or_create_domain <name> <description>
643function get_or_create_domain {
Steve Martinellib74e01c2014-12-18 01:35:35 -0500644 local os_url="$KEYSTONE_SERVICE_URI_V3"
Alistair Coles24779f62014-10-15 18:57:59 +0100645 # Gets domain id
646 local domain_id=$(
647 # Gets domain id
648 openstack --os-token=$OS_TOKEN --os-url=$os_url \
649 --os-identity-api-version=3 domain show $1 \
650 -f value -c id 2>/dev/null ||
651 # Creates new domain
652 openstack --os-token=$OS_TOKEN --os-url=$os_url \
653 --os-identity-api-version=3 domain create $1 \
654 --description "$2" \
655 -f value -c id
656 )
657 echo $domain_id
658}
659
Steve Martinellib74e01c2014-12-18 01:35:35 -0500660# Gets or creates group
661# Usage: get_or_create_group <groupname> [<domain> <description>]
662function get_or_create_group {
663 local domain=${2:+--domain ${2}}
664 local desc="${3:-}"
665 local os_url="$KEYSTONE_SERVICE_URI_V3"
666 # Gets group id
667 local group_id=$(
668 # Creates new group with --or-show
669 openstack --os-token=$OS_TOKEN --os-url=$os_url \
670 --os-identity-api-version=3 group create $1 \
671 $domain --description "$desc" --or-show \
672 -f value -c id
673 )
674 echo $group_id
675}
676
Bartosz Górski0abde392014-02-28 14:15:19 +0100677# Gets or creates user
Jamie Lennox18f39bf2015-01-28 13:38:32 +1000678# Usage: get_or_create_user <username> <password> [<email> [<domain>]]
Bartosz Górski0abde392014-02-28 14:15:19 +0100679function get_or_create_user {
Jamie Lennox18f39bf2015-01-28 13:38:32 +1000680 if [[ ! -z "$3" ]]; then
681 local email="--email=$3"
Gael Chamoulaud6dd8a8b2014-07-22 01:12:12 +0200682 else
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500683 local email=""
Gael Chamoulaud6dd8a8b2014-07-22 01:12:12 +0200684 fi
Alistair Coles24779f62014-10-15 18:57:59 +0100685 local os_cmd="openstack"
686 local domain=""
Jamie Lennox18f39bf2015-01-28 13:38:32 +1000687 if [[ ! -z "$4" ]]; then
688 domain="--domain=$4"
Steve Martinellib74e01c2014-12-18 01:35:35 -0500689 os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI_V3 --os-identity-api-version=3"
Alistair Coles24779f62014-10-15 18:57:59 +0100690 fi
Bartosz Górski0abde392014-02-28 14:15:19 +0100691 # Gets user id
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500692 local user_id=$(
Steve Martinelli245daa22014-11-14 02:17:22 -0500693 # Creates new user with --or-show
Alistair Coles24779f62014-10-15 18:57:59 +0100694 $os_cmd user create \
Bartosz Górski0abde392014-02-28 14:15:19 +0100695 $1 \
696 --password "$2" \
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500697 $email \
Alistair Coles24779f62014-10-15 18:57:59 +0100698 $domain \
Steve Martinelli245daa22014-11-14 02:17:22 -0500699 --or-show \
Bartosz Górski0abde392014-02-28 14:15:19 +0100700 -f value -c id
701 )
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500702 echo $user_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100703}
704
705# Gets or creates project
Alistair Coles24779f62014-10-15 18:57:59 +0100706# Usage: get_or_create_project <name> [<domain>]
Bartosz Górski0abde392014-02-28 14:15:19 +0100707function get_or_create_project {
708 # Gets project id
Alistair Coles24779f62014-10-15 18:57:59 +0100709 local os_cmd="openstack"
710 local domain=""
711 if [[ ! -z "$2" ]]; then
712 domain="--domain=$2"
Steve Martinellib74e01c2014-12-18 01:35:35 -0500713 os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI_V3 --os-identity-api-version=3"
Alistair Coles24779f62014-10-15 18:57:59 +0100714 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500715 local project_id=$(
Steve Martinelli245daa22014-11-14 02:17:22 -0500716 # Creates new project with --or-show
717 $os_cmd project create $1 $domain --or-show -f value -c id
Bartosz Górski0abde392014-02-28 14:15:19 +0100718 )
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500719 echo $project_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100720}
721
722# Gets or creates role
723# Usage: get_or_create_role <name>
724function get_or_create_role {
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500725 local role_id=$(
Steve Martinelli245daa22014-11-14 02:17:22 -0500726 # Creates role with --or-show
727 openstack role create $1 --or-show -f value -c id
Bartosz Górski0abde392014-02-28 14:15:19 +0100728 )
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500729 echo $role_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100730}
731
Jamie Lennox9b215db2015-02-10 18:19:57 +1100732# Gets or adds user role to project
733# Usage: get_or_add_user_project_role <role> <user> <project>
734function get_or_add_user_project_role {
Bartosz Górski0abde392014-02-28 14:15:19 +0100735 # Gets user role id
Steve Martinelli5541a612015-01-19 15:58:49 -0500736 local user_role_id=$(openstack role list \
737 --user $2 \
Bartosz Górski0abde392014-02-28 14:15:19 +0100738 --project $3 \
739 --column "ID" \
740 --column "Name" \
741 | grep " $1 " | get_field 1)
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500742 if [[ -z "$user_role_id" ]]; then
Bartosz Górski0abde392014-02-28 14:15:19 +0100743 # Adds role to user
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500744 user_role_id=$(openstack role add \
Bartosz Górski0abde392014-02-28 14:15:19 +0100745 $1 \
746 --user $2 \
747 --project $3 \
748 | grep " id " | get_field 2)
749 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500750 echo $user_role_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100751}
752
753# Gets or creates service
754# Usage: get_or_create_service <name> <type> <description>
755function get_or_create_service {
756 # Gets service id
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500757 local service_id=$(
Bartosz Górski0abde392014-02-28 14:15:19 +0100758 # Gets service id
759 openstack service show $1 -f value -c id 2>/dev/null ||
760 # Creates new service if not exists
761 openstack service create \
Steve Martinelli789af5c2015-01-19 16:11:44 -0500762 $2 \
763 --name $1 \
Bartosz Górski0abde392014-02-28 14:15:19 +0100764 --description="$3" \
765 -f value -c id
766 )
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500767 echo $service_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100768}
769
770# Gets or creates endpoint
771# Usage: get_or_create_endpoint <service> <region> <publicurl> <adminurl> <internalurl>
772function get_or_create_endpoint {
773 # Gets endpoint id
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500774 local endpoint_id=$(openstack endpoint list \
Bartosz Górski0abde392014-02-28 14:15:19 +0100775 --column "ID" \
776 --column "Region" \
777 --column "Service Name" \
778 | grep " $2 " \
779 | grep " $1 " | get_field 1)
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500780 if [[ -z "$endpoint_id" ]]; then
Bartosz Górski0abde392014-02-28 14:15:19 +0100781 # Creates new endpoint
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500782 endpoint_id=$(openstack endpoint create \
Bartosz Górski0abde392014-02-28 14:15:19 +0100783 $1 \
784 --region $2 \
785 --publicurl $3 \
786 --adminurl $4 \
787 --internalurl $5 \
788 | grep " id " | get_field 2)
789 fi
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500790 echo $endpoint_id
Bartosz Górski0abde392014-02-28 14:15:19 +0100791}
Dean Troyerdff49a22014-01-30 15:37:40 -0600792
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500793
Dean Troyerdff49a22014-01-30 15:37:40 -0600794# Package Functions
795# =================
796
797# _get_package_dir
Ian Wienandaee18c72014-02-21 15:35:08 +1100798function _get_package_dir {
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800799 local base_dir=$1
Dean Troyerdff49a22014-01-30 15:37:40 -0600800 local pkg_dir
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800801
802 if [[ -z "$base_dir" ]]; then
803 base_dir=$FILES
804 fi
Dean Troyerdff49a22014-01-30 15:37:40 -0600805 if is_ubuntu; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800806 pkg_dir=$base_dir/debs
Dean Troyerdff49a22014-01-30 15:37:40 -0600807 elif is_fedora; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800808 pkg_dir=$base_dir/rpms
Dean Troyerdff49a22014-01-30 15:37:40 -0600809 elif is_suse; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800810 pkg_dir=$base_dir/rpms-suse
Dean Troyerdff49a22014-01-30 15:37:40 -0600811 else
812 exit_distro_not_supported "list of packages"
813 fi
814 echo "$pkg_dir"
815}
816
817# Wrapper for ``apt-get`` to set cache and proxy environment variables
818# Uses globals ``OFFLINE``, ``*_proxy``
819# apt_get operation package [package ...]
Ian Wienandaee18c72014-02-21 15:35:08 +1100820function apt_get {
Sean Dague45917cc2014-02-24 16:09:14 -0500821 local xtrace=$(set +o | grep xtrace)
822 set +o xtrace
823
Dean Troyerdff49a22014-01-30 15:37:40 -0600824 [[ "$OFFLINE" = "True" || -z "$@" ]] && return
825 local sudo="sudo"
826 [[ "$(id -u)" = "0" ]] && sudo="env"
Sean Dague45917cc2014-02-24 16:09:14 -0500827
828 $xtrace
Sean Dague53753292014-12-04 19:38:15 -0500829
Dean Troyerdff49a22014-01-30 15:37:40 -0600830 $sudo DEBIAN_FRONTEND=noninteractive \
Sean Dague53753292014-12-04 19:38:15 -0500831 http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \
832 no_proxy=${no_proxy:-} \
Dean Troyerdff49a22014-01-30 15:37:40 -0600833 apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
834}
835
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800836function _parse_package_files {
837 local files_to_parse=$@
Dean Troyerdff49a22014-01-30 15:37:40 -0600838
Dean Troyerdff49a22014-01-30 15:37:40 -0600839 if [[ -z "$DISTRO" ]]; then
840 GetDistro
841 fi
Dean Troyerdff49a22014-01-30 15:37:40 -0600842
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800843 for fname in ${files_to_parse}; do
Dean Troyerdff49a22014-01-30 15:37:40 -0600844 local OIFS line package distros distro
845 [[ -e $fname ]] || continue
846
847 OIFS=$IFS
848 IFS=$'\n'
849 for line in $(<${fname}); do
850 if [[ $line =~ "NOPRIME" ]]; then
851 continue
852 fi
853
854 # Assume we want this package
855 package=${line%#*}
856 inst_pkg=1
857
858 # Look for # dist:xxx in comment
859 if [[ $line =~ (.*)#.*dist:([^ ]*) ]]; then
860 # We are using BASH regexp matching feature.
861 package=${BASH_REMATCH[1]}
862 distros=${BASH_REMATCH[2]}
863 # In bash ${VAR,,} will lowecase VAR
864 # Look for a match in the distro list
865 if [[ ! ${distros,,} =~ ${DISTRO,,} ]]; then
866 # If no match then skip this package
867 inst_pkg=0
868 fi
869 fi
870
871 # Look for # testonly in comment
872 if [[ $line =~ (.*)#.*testonly.* ]]; then
873 package=${BASH_REMATCH[1]}
874 # Are we installing test packages? (test for the default value)
875 if [[ $INSTALL_TESTONLY_PACKAGES = "False" ]]; then
876 # If not installing test packages the skip this package
877 inst_pkg=0
878 fi
879 fi
880
881 if [[ $inst_pkg = 1 ]]; then
882 echo $package
883 fi
884 done
885 IFS=$OIFS
886 done
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800887}
888
889# get_packages() collects a list of package names of any type from the
890# prerequisite files in ``files/{debs|rpms}``. The list is intended
891# to be passed to a package installer such as apt or yum.
892#
893# Only packages required for the services in 1st argument will be
894# included. Two bits of metadata are recognized in the prerequisite files:
895#
896# - ``# NOPRIME`` defers installation to be performed later in `stack.sh`
897# - ``# dist:DISTRO`` or ``dist:DISTRO1,DISTRO2`` limits the selection
898# of the package to the distros listed. The distro names are case insensitive.
899function get_packages {
900 local xtrace=$(set +o | grep xtrace)
901 set +o xtrace
902 local services=$@
903 local package_dir=$(_get_package_dir)
904 local file_to_parse=""
905 local service=""
906
907 INSTALL_TESTONLY_PACKAGES=$(trueorfalse False INSTALL_TESTONLY_PACKAGES)
908
909 if [[ -z "$package_dir" ]]; then
910 echo "No package directory supplied"
911 return 1
912 fi
913 for service in ${services//,/ }; do
914 # Allow individual services to specify dependencies
915 if [[ -e ${package_dir}/${service} ]]; then
916 file_to_parse="${file_to_parse} ${package_dir}/${service}"
917 fi
918 # NOTE(sdague) n-api needs glance for now because that's where
919 # glance client is
920 if [[ $service == n-api ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700921 if [[ ! $file_to_parse =~ $package_dir/nova ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800922 file_to_parse="${file_to_parse} ${package_dir}/nova"
923 fi
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700924 if [[ ! $file_to_parse =~ $package_dir/glance ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800925 file_to_parse="${file_to_parse} ${package_dir}/glance"
926 fi
927 elif [[ $service == c-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700928 if [[ ! $file_to_parse =~ $package_dir/cinder ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800929 file_to_parse="${file_to_parse} ${package_dir}/cinder"
930 fi
931 elif [[ $service == ceilometer-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700932 if [[ ! $file_to_parse =~ $package_dir/ceilometer ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800933 file_to_parse="${file_to_parse} ${package_dir}/ceilometer"
934 fi
935 elif [[ $service == s-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700936 if [[ ! $file_to_parse =~ $package_dir/swift ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800937 file_to_parse="${file_to_parse} ${package_dir}/swift"
938 fi
939 elif [[ $service == n-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700940 if [[ ! $file_to_parse =~ $package_dir/nova ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800941 file_to_parse="${file_to_parse} ${package_dir}/nova"
942 fi
943 elif [[ $service == g-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700944 if [[ ! $file_to_parse =~ $package_dir/glance ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800945 file_to_parse="${file_to_parse} ${package_dir}/glance"
946 fi
947 elif [[ $service == key* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700948 if [[ ! $file_to_parse =~ $package_dir/keystone ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800949 file_to_parse="${file_to_parse} ${package_dir}/keystone"
950 fi
951 elif [[ $service == q-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700952 if [[ ! $file_to_parse =~ $package_dir/neutron ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800953 file_to_parse="${file_to_parse} ${package_dir}/neutron"
954 fi
955 elif [[ $service == ir-* ]]; then
Ryan Hsu6f3f3102015-03-19 16:26:45 -0700956 if [[ ! $file_to_parse =~ $package_dir/ironic ]]; then
Adam Gandelman7ca90cd2015-03-04 17:25:07 -0800957 file_to_parse="${file_to_parse} ${package_dir}/ironic"
958 fi
959 fi
960 done
961 echo "$(_parse_package_files $file_to_parse)"
962 $xtrace
963}
964
965# get_plugin_packages() collects a list of package names of any type from a
966# plugin's prerequisite files in ``$PLUGIN/devstack/files/{debs|rpms}``. The
967# list is intended to be passed to a package installer such as apt or yum.
968#
969# Only packages required for enabled and collected plugins will included.
970#
971# The same metadata used in the main devstack prerequisite files may be used
972# in these prerequisite files, see get_packages() for more info.
973function get_plugin_packages {
974 local xtrace=$(set +o | grep xtrace)
975 set +o xtrace
976 local files_to_parse=""
977 local package_dir=""
978 for plugin in ${DEVSTACK_PLUGINS//,/ }; do
979 local package_dir="$(_get_package_dir ${GITDIR[$plugin]}/devstack/files)"
980 files_to_parse+="$package_dir/$plugin"
981 done
982 echo "$(_parse_package_files $files_to_parse)"
Sean Dague45917cc2014-02-24 16:09:14 -0500983 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -0600984}
985
986# Distro-agnostic package installer
Dean Troyerd5dfa4c2014-07-25 11:13:11 -0500987# Uses globals ``NO_UPDATE_REPOS``, ``REPOS_UPDATED``, ``RETRY_UPDATE``
Dean Troyerdff49a22014-01-30 15:37:40 -0600988# install_package package [package ...]
Monty Taylor5cc6d2c2014-06-06 08:45:16 -0400989function update_package_repo {
Sean Dague53753292014-12-04 19:38:15 -0500990 NO_UPDATE_REPOS=${NO_UPDATE_REPOS:-False}
991 REPOS_UPDATED=${REPOS_UPDATED:-False}
992 RETRY_UPDATE=${RETRY_UPDATE:-False}
993
Paul Linchpiner9e179742014-07-13 22:23:00 -0700994 if [[ "$NO_UPDATE_REPOS" = "True" ]]; then
Monty Taylor5cc6d2c2014-06-06 08:45:16 -0400995 return 0
996 fi
Dean Troyerdff49a22014-01-30 15:37:40 -0600997
Monty Taylor5cc6d2c2014-06-06 08:45:16 -0400998 if is_ubuntu; then
999 local xtrace=$(set +o | grep xtrace)
1000 set +o xtrace
1001 if [[ "$REPOS_UPDATED" != "True" || "$RETRY_UPDATE" = "True" ]]; then
1002 # if there are transient errors pulling the updates, that's fine.
1003 # It may be secondary repositories that we don't really care about.
1004 apt_get update || /bin/true
1005 REPOS_UPDATED=True
1006 fi
Sean Dague45917cc2014-02-24 16:09:14 -05001007 $xtrace
Monty Taylor5cc6d2c2014-06-06 08:45:16 -04001008 fi
1009}
1010
1011function real_install_package {
1012 if is_ubuntu; then
Dean Troyerdff49a22014-01-30 15:37:40 -06001013 apt_get install "$@"
1014 elif is_fedora; then
1015 yum_install "$@"
1016 elif is_suse; then
1017 zypper_install "$@"
1018 else
1019 exit_distro_not_supported "installing packages"
1020 fi
1021}
1022
Monty Taylor5cc6d2c2014-06-06 08:45:16 -04001023# Distro-agnostic package installer
1024# install_package package [package ...]
1025function install_package {
1026 update_package_repo
1027 real_install_package $@ || RETRY_UPDATE=True update_package_repo && real_install_package $@
1028}
1029
Dean Troyerdff49a22014-01-30 15:37:40 -06001030# Distro-agnostic function to tell if a package is installed
1031# is_package_installed package [package ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001032function is_package_installed {
Dean Troyerdff49a22014-01-30 15:37:40 -06001033 if [[ -z "$@" ]]; then
1034 return 1
1035 fi
1036
1037 if [[ -z "$os_PACKAGE" ]]; then
1038 GetOSVersion
1039 fi
1040
1041 if [[ "$os_PACKAGE" = "deb" ]]; then
1042 dpkg -s "$@" > /dev/null 2> /dev/null
1043 elif [[ "$os_PACKAGE" = "rpm" ]]; then
1044 rpm --quiet -q "$@"
1045 else
1046 exit_distro_not_supported "finding if a package is installed"
1047 fi
1048}
1049
1050# Distro-agnostic package uninstaller
1051# uninstall_package package [package ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001052function uninstall_package {
Dean Troyerdff49a22014-01-30 15:37:40 -06001053 if is_ubuntu; then
1054 apt_get purge "$@"
1055 elif is_fedora; then
Ian Wienand36298ee2015-02-04 10:29:31 +11001056 sudo ${YUM:-yum} remove -y "$@" ||:
Dean Troyerdff49a22014-01-30 15:37:40 -06001057 elif is_suse; then
1058 sudo zypper rm "$@"
1059 else
1060 exit_distro_not_supported "uninstalling packages"
1061 fi
1062}
1063
1064# Wrapper for ``yum`` to set proxy environment variables
Daniel P. Berrange63d25d92014-12-09 15:21:22 +00001065# Uses globals ``OFFLINE``, ``*_proxy``, ``YUM``
Dean Troyerdff49a22014-01-30 15:37:40 -06001066# yum_install package [package ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001067function yum_install {
Dean Troyerdff49a22014-01-30 15:37:40 -06001068 [[ "$OFFLINE" = "True" ]] && return
1069 local sudo="sudo"
1070 [[ "$(id -u)" = "0" ]] && sudo="env"
Ian Wienandb27f16d2014-02-28 14:29:02 +11001071
1072 # The manual check for missing packages is because yum -y assumes
1073 # missing packages are OK. See
1074 # https://bugzilla.redhat.com/show_bug.cgi?id=965567
Ian Wienandfdf00f22015-03-13 11:50:02 +11001075 $sudo http_proxy="${http_proxy:-}" https_proxy="${https_proxy:-}" \
1076 no_proxy="${no_proxy:-}" \
Ian Wienand36298ee2015-02-04 10:29:31 +11001077 ${YUM:-yum} install -y "$@" 2>&1 | \
Ian Wienandb27f16d2014-02-28 14:29:02 +11001078 awk '
1079 BEGIN { fail=0 }
1080 /No package/ { fail=1 }
1081 { print }
1082 END { exit fail }' || \
1083 die $LINENO "Missing packages detected"
1084
1085 # also ensure we catch a yum failure
1086 if [[ ${PIPESTATUS[0]} != 0 ]]; then
Ian Wienand36298ee2015-02-04 10:29:31 +11001087 die $LINENO "${YUM:-yum} install failure"
Ian Wienandb27f16d2014-02-28 14:29:02 +11001088 fi
Dean Troyerdff49a22014-01-30 15:37:40 -06001089}
1090
1091# zypper wrapper to set arguments correctly
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001092# Uses globals ``OFFLINE``, ``*_proxy``
Dean Troyerdff49a22014-01-30 15:37:40 -06001093# zypper_install package [package ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001094function zypper_install {
Dean Troyerdff49a22014-01-30 15:37:40 -06001095 [[ "$OFFLINE" = "True" ]] && return
1096 local sudo="sudo"
1097 [[ "$(id -u)" = "0" ]] && sudo="env"
Ian Wienandfdf00f22015-03-13 11:50:02 +11001098 $sudo http_proxy="${http_proxy:-}" https_proxy="${https_proxy:-}" \
1099 no_proxy="${no_proxy:-}" \
Dean Troyerdff49a22014-01-30 15:37:40 -06001100 zypper --non-interactive install --auto-agree-with-licenses "$@"
1101}
1102
1103
1104# Process Functions
1105# =================
1106
1107# _run_process() is designed to be backgrounded by run_process() to simulate a
1108# fork. It includes the dirty work of closing extra filehandles and preparing log
1109# files to produce the same logs as screen_it(). The log filename is derived
Dean Troyerdde41d02014-12-09 17:47:57 -06001110# from the service name.
1111# Uses globals ``CURRENT_LOG_TIME``, ``LOGDIR``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
Chris Dent2f27a0e2014-09-09 13:46:02 +01001112# If an optional group is provided sg will be used to set the group of
1113# the command.
1114# _run_process service "command-line" [group]
Ian Wienandaee18c72014-02-21 15:35:08 +11001115function _run_process {
Dean Troyerdff49a22014-01-30 15:37:40 -06001116 local service=$1
1117 local command="$2"
Chris Dent2f27a0e2014-09-09 13:46:02 +01001118 local group=$3
Dean Troyerdff49a22014-01-30 15:37:40 -06001119
1120 # Undo logging redirections and close the extra descriptors
1121 exec 1>&3
1122 exec 2>&3
1123 exec 3>&-
1124 exec 6>&-
1125
Dean Troyerdde41d02014-12-09 17:47:57 -06001126 local real_logfile="${LOGDIR}/${service}.log.${CURRENT_LOG_TIME}"
1127 if [[ -n ${LOGDIR} ]]; then
1128 exec 1>&"$real_logfile" 2>&1
1129 ln -sf "$real_logfile" ${LOGDIR}/${service}.log
1130 if [[ -n ${SCREEN_LOGDIR} ]]; then
1131 # Drop the backward-compat symlink
1132 ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${service}.log
1133 fi
Dean Troyerdff49a22014-01-30 15:37:40 -06001134
1135 # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
1136 export PYTHONUNBUFFERED=1
1137 fi
1138
Dean Troyer3159a822014-08-27 14:13:58 -05001139 # Run under ``setsid`` to force the process to become a session and group leader.
1140 # The pid saved can be used with pkill -g to get the entire process group.
Chris Dent2f27a0e2014-09-09 13:46:02 +01001141 if [[ -n "$group" ]]; then
1142 setsid sg $group "$command" & echo $! >$SERVICE_DIR/$SCREEN_NAME/$service.pid
1143 else
1144 setsid $command & echo $! >$SERVICE_DIR/$SCREEN_NAME/$service.pid
1145 fi
Dean Troyer3159a822014-08-27 14:13:58 -05001146
1147 # Just silently exit this process
1148 exit 0
Dean Troyerdff49a22014-01-30 15:37:40 -06001149}
1150
1151# Helper to remove the ``*.failure`` files under ``$SERVICE_DIR/$SCREEN_NAME``.
1152# This is used for ``service_check`` when all the ``screen_it`` are called finished
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001153# Uses globals ``SCREEN_NAME``, ``SERVICE_DIR``
Dean Troyerdff49a22014-01-30 15:37:40 -06001154# init_service_check
Ian Wienandaee18c72014-02-21 15:35:08 +11001155function init_service_check {
Dean Troyerdff49a22014-01-30 15:37:40 -06001156 SCREEN_NAME=${SCREEN_NAME:-stack}
1157 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
1158
1159 if [[ ! -d "$SERVICE_DIR/$SCREEN_NAME" ]]; then
1160 mkdir -p "$SERVICE_DIR/$SCREEN_NAME"
1161 fi
1162
1163 rm -f "$SERVICE_DIR/$SCREEN_NAME"/*.failure
1164}
1165
1166# Find out if a process exists by partial name.
1167# is_running name
Ian Wienandaee18c72014-02-21 15:35:08 +11001168function is_running {
Dean Troyerdff49a22014-01-30 15:37:40 -06001169 local name=$1
1170 ps auxw | grep -v grep | grep ${name} > /dev/null
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001171 local exitcode=$?
Dean Troyerdff49a22014-01-30 15:37:40 -06001172 # some times I really hate bash reverse binary logic
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001173 return $exitcode
Dean Troyerdff49a22014-01-30 15:37:40 -06001174}
1175
Dean Troyer3159a822014-08-27 14:13:58 -05001176# Run a single service under screen or directly
1177# If the command includes shell metachatacters (;<>*) it must be run using a shell
Chris Dent2f27a0e2014-09-09 13:46:02 +01001178# If an optional group is provided sg will be used to run the
1179# command as that group.
1180# run_process service "command-line" [group]
Ian Wienandaee18c72014-02-21 15:35:08 +11001181function run_process {
Dean Troyerdff49a22014-01-30 15:37:40 -06001182 local service=$1
1183 local command="$2"
Chris Dent2f27a0e2014-09-09 13:46:02 +01001184 local group=$3
Dean Troyerdff49a22014-01-30 15:37:40 -06001185
Dean Troyer3159a822014-08-27 14:13:58 -05001186 if is_service_enabled $service; then
1187 if [[ "$USE_SCREEN" = "True" ]]; then
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001188 screen_process "$service" "$command" "$group"
Dean Troyer3159a822014-08-27 14:13:58 -05001189 else
1190 # Spawn directly without screen
Chris Dent2f27a0e2014-09-09 13:46:02 +01001191 _run_process "$service" "$command" "$group" &
Dean Troyer3159a822014-08-27 14:13:58 -05001192 fi
1193 fi
Dean Troyerdff49a22014-01-30 15:37:40 -06001194}
1195
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001196# Helper to launch a process in a named screen
Dean Troyerdde41d02014-12-09 17:47:57 -06001197# Uses globals ``CURRENT_LOG_TIME``, ```LOGDIR``, ``SCREEN_LOGDIR``, `SCREEN_NAME``,
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001198# ``SERVICE_DIR``, ``USE_SCREEN``
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001199# screen_process name "command-line" [group]
Chris Dent2f27a0e2014-09-09 13:46:02 +01001200# Run a command in a shell in a screen window, if an optional group
1201# is provided, use sg to set the group of the command.
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001202function screen_process {
1203 local name=$1
Dean Troyer3159a822014-08-27 14:13:58 -05001204 local command="$2"
Chris Dent2f27a0e2014-09-09 13:46:02 +01001205 local group=$3
Dean Troyer3159a822014-08-27 14:13:58 -05001206
Sean Dagueea22a4f2014-06-27 15:21:41 -04001207 SCREEN_NAME=${SCREEN_NAME:-stack}
1208 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
Sean Dague53753292014-12-04 19:38:15 -05001209 USE_SCREEN=$(trueorfalse True USE_SCREEN)
Dean Troyerdff49a22014-01-30 15:37:40 -06001210
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001211 # Append the process to the screen rc file
1212 screen_rc "$name" "$command"
Dean Troyerdff49a22014-01-30 15:37:40 -06001213
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001214 screen -S $SCREEN_NAME -X screen -t $name
Dean Troyerdff49a22014-01-30 15:37:40 -06001215
Dean Troyerdde41d02014-12-09 17:47:57 -06001216 local real_logfile="${LOGDIR}/${name}.log.${CURRENT_LOG_TIME}"
1217 echo "LOGDIR: $LOGDIR"
1218 echo "SCREEN_LOGDIR: $SCREEN_LOGDIR"
1219 echo "log: $real_logfile"
1220 if [[ -n ${LOGDIR} ]]; then
1221 screen -S $SCREEN_NAME -p $name -X logfile "$real_logfile"
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001222 screen -S $SCREEN_NAME -p $name -X log on
Dean Troyerdde41d02014-12-09 17:47:57 -06001223 ln -sf "$real_logfile" ${LOGDIR}/${name}.log
1224 if [[ -n ${SCREEN_LOGDIR} ]]; then
1225 # Drop the backward-compat symlink
1226 ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${1}.log
1227 fi
Dean Troyerdff49a22014-01-30 15:37:40 -06001228 fi
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001229
1230 # sleep to allow bash to be ready to be send the command - we are
1231 # creating a new window in screen and then sends characters, so if
1232 # bash isn't running by the time we send the command, nothing happens
1233 sleep 3
1234
1235 NL=`echo -ne '\015'`
1236 # This fun command does the following:
1237 # - the passed server command is backgrounded
1238 # - the pid of the background process is saved in the usual place
1239 # - the server process is brought back to the foreground
1240 # - if the server process exits prematurely the fg command errors
1241 # and a message is written to stdout and the process failure file
1242 #
1243 # The pid saved can be used in stop_process() as a process group
1244 # id to kill off all child processes
1245 if [[ -n "$group" ]]; then
1246 command="sg $group '$command'"
1247 fi
1248 screen -S $SCREEN_NAME -p $name -X stuff "$command & echo \$! >$SERVICE_DIR/$SCREEN_NAME/${name}.pid; fg || echo \"$name failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/${name}.failure\"$NL"
Dean Troyerdff49a22014-01-30 15:37:40 -06001249}
1250
1251# Screen rc file builder
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001252# Uses globals ``SCREEN_NAME``, ``SCREENRC``
Dean Troyerdff49a22014-01-30 15:37:40 -06001253# screen_rc service "command-line"
1254function screen_rc {
1255 SCREEN_NAME=${SCREEN_NAME:-stack}
1256 SCREENRC=$TOP_DIR/$SCREEN_NAME-screenrc
1257 if [[ ! -e $SCREENRC ]]; then
1258 # Name the screen session
1259 echo "sessionname $SCREEN_NAME" > $SCREENRC
1260 # Set a reasonable statusbar
1261 echo "hardstatus alwayslastline '$SCREEN_HARDSTATUS'" >> $SCREENRC
1262 # Some distributions override PROMPT_COMMAND for the screen terminal type - turn that off
1263 echo "setenv PROMPT_COMMAND /bin/true" >> $SCREENRC
1264 echo "screen -t shell bash" >> $SCREENRC
1265 fi
1266 # If this service doesn't already exist in the screenrc file
1267 if ! grep $1 $SCREENRC 2>&1 > /dev/null; then
1268 NL=`echo -ne '\015'`
1269 echo "screen -t $1 bash" >> $SCREENRC
1270 echo "stuff \"$2$NL\"" >> $SCREENRC
1271
Dean Troyerdde41d02014-12-09 17:47:57 -06001272 if [[ -n ${LOGDIR} ]]; then
1273 echo "logfile ${LOGDIR}/${1}.log.${CURRENT_LOG_TIME}" >>$SCREENRC
Dean Troyerdff49a22014-01-30 15:37:40 -06001274 echo "log on" >>$SCREENRC
1275 fi
1276 fi
1277}
1278
1279# Stop a service in screen
1280# If a PID is available use it, kill the whole process group via TERM
1281# If screen is being used kill the screen window; this will catch processes
1282# that did not leave a PID behind
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001283# Uses globals ``SCREEN_NAME``, ``SERVICE_DIR``, ``USE_SCREEN``
Chris Dent2f27a0e2014-09-09 13:46:02 +01001284# screen_stop_service service
Dean Troyer3159a822014-08-27 14:13:58 -05001285function screen_stop_service {
1286 local service=$1
1287
Dean Troyerdff49a22014-01-30 15:37:40 -06001288 SCREEN_NAME=${SCREEN_NAME:-stack}
1289 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
Sean Dague53753292014-12-04 19:38:15 -05001290 USE_SCREEN=$(trueorfalse True USE_SCREEN)
Dean Troyerdff49a22014-01-30 15:37:40 -06001291
Dean Troyer3159a822014-08-27 14:13:58 -05001292 if is_service_enabled $service; then
1293 # Clean up the screen window
1294 screen -S $SCREEN_NAME -p $service -X kill
1295 fi
1296}
1297
1298# Stop a service process
1299# If a PID is available use it, kill the whole process group via TERM
1300# If screen is being used kill the screen window; this will catch processes
1301# that did not leave a PID behind
1302# Uses globals ``SERVICE_DIR``, ``USE_SCREEN``
1303# stop_process service
1304function stop_process {
1305 local service=$1
1306
1307 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
Sean Dague53753292014-12-04 19:38:15 -05001308 USE_SCREEN=$(trueorfalse True USE_SCREEN)
Dean Troyer3159a822014-08-27 14:13:58 -05001309
1310 if is_service_enabled $service; then
Dean Troyerdff49a22014-01-30 15:37:40 -06001311 # Kill via pid if we have one available
Dean Troyer3159a822014-08-27 14:13:58 -05001312 if [[ -r $SERVICE_DIR/$SCREEN_NAME/$service.pid ]]; then
1313 pkill -g $(cat $SERVICE_DIR/$SCREEN_NAME/$service.pid)
1314 rm $SERVICE_DIR/$SCREEN_NAME/$service.pid
Dean Troyerdff49a22014-01-30 15:37:40 -06001315 fi
1316 if [[ "$USE_SCREEN" = "True" ]]; then
1317 # Clean up the screen window
Dean Troyer3159a822014-08-27 14:13:58 -05001318 screen_stop_service $service
Dean Troyerdff49a22014-01-30 15:37:40 -06001319 fi
1320 fi
1321}
1322
1323# Helper to get the status of each running service
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001324# Uses globals ``SCREEN_NAME``, ``SERVICE_DIR``
Dean Troyerdff49a22014-01-30 15:37:40 -06001325# service_check
Ian Wienandaee18c72014-02-21 15:35:08 +11001326function service_check {
Dean Troyerdff49a22014-01-30 15:37:40 -06001327 local service
1328 local failures
1329 SCREEN_NAME=${SCREEN_NAME:-stack}
1330 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
1331
1332
1333 if [[ ! -d "$SERVICE_DIR/$SCREEN_NAME" ]]; then
1334 echo "No service status directory found"
1335 return
1336 fi
1337
1338 # Check if there is any falure flag file under $SERVICE_DIR/$SCREEN_NAME
Sean Dague09bd7c82014-02-03 08:35:26 +09001339 # make this -o errexit safe
1340 failures=`ls "$SERVICE_DIR/$SCREEN_NAME"/*.failure 2>/dev/null || /bin/true`
Dean Troyerdff49a22014-01-30 15:37:40 -06001341
1342 for service in $failures; do
1343 service=`basename $service`
1344 service=${service%.failure}
1345 echo "Error: Service $service is not running"
1346 done
1347
1348 if [ -n "$failures" ]; then
Sean Dague12379222014-02-27 17:16:46 -05001349 die $LINENO "More details about the above errors can be found with screen, with ./rejoin-stack.sh"
Dean Troyerdff49a22014-01-30 15:37:40 -06001350 fi
1351}
1352
Chris Dent2f27a0e2014-09-09 13:46:02 +01001353# Tail a log file in a screen if USE_SCREEN is true.
1354function tail_log {
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001355 local name=$1
Chris Dent2f27a0e2014-09-09 13:46:02 +01001356 local logfile=$2
1357
Sean Dague53753292014-12-04 19:38:15 -05001358 USE_SCREEN=$(trueorfalse True USE_SCREEN)
Chris Dent2f27a0e2014-09-09 13:46:02 +01001359 if [[ "$USE_SCREEN" = "True" ]]; then
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001360 screen_process "$name" "sudo tail -f $logfile"
Chris Dent2f27a0e2014-09-09 13:46:02 +01001361 fi
1362}
1363
Dean Troyerdff49a22014-01-30 15:37:40 -06001364
Dean Troyer3159a822014-08-27 14:13:58 -05001365# Deprecated Functions
1366# --------------------
1367
1368# _old_run_process() is designed to be backgrounded by old_run_process() to simulate a
1369# fork. It includes the dirty work of closing extra filehandles and preparing log
1370# files to produce the same logs as screen_it(). The log filename is derived
1371# from the service name and global-and-now-misnamed ``SCREEN_LOGDIR``
1372# Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
1373# _old_run_process service "command-line"
1374function _old_run_process {
1375 local service=$1
1376 local command="$2"
1377
1378 # Undo logging redirections and close the extra descriptors
1379 exec 1>&3
1380 exec 2>&3
1381 exec 3>&-
1382 exec 6>&-
1383
1384 if [[ -n ${SCREEN_LOGDIR} ]]; then
Dean Troyerad5cc982014-12-10 16:35:32 -06001385 exec 1>&${SCREEN_LOGDIR}/screen-${1}.log.${CURRENT_LOG_TIME} 2>&1
1386 ln -sf ${SCREEN_LOGDIR}/screen-${1}.log.${CURRENT_LOG_TIME} ${SCREEN_LOGDIR}/screen-${1}.log
Dean Troyer3159a822014-08-27 14:13:58 -05001387
1388 # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
1389 export PYTHONUNBUFFERED=1
1390 fi
1391
1392 exec /bin/bash -c "$command"
1393 die "$service exec failure: $command"
1394}
1395
1396# old_run_process() launches a child process that closes all file descriptors and
1397# then exec's the passed in command. This is meant to duplicate the semantics
1398# of screen_it() without screen. PIDs are written to
1399# ``$SERVICE_DIR/$SCREEN_NAME/$service.pid`` by the spawned child process.
1400# old_run_process service "command-line"
1401function old_run_process {
1402 local service=$1
1403 local command="$2"
1404
1405 # Spawn the child process
1406 _old_run_process "$service" "$command" &
1407 echo $!
1408}
1409
1410# Compatibility for existing start_XXXX() functions
1411# Uses global ``USE_SCREEN``
1412# screen_it service "command-line"
1413function screen_it {
1414 if is_service_enabled $1; then
1415 # Append the service to the screen rc file
1416 screen_rc "$1" "$2"
1417
1418 if [[ "$USE_SCREEN" = "True" ]]; then
Adam Gandelman8543a0f2014-10-16 17:42:33 -07001419 screen_process "$1" "$2"
Dean Troyer3159a822014-08-27 14:13:58 -05001420 else
1421 # Spawn directly without screen
1422 old_run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$1.pid
1423 fi
1424 fi
1425}
1426
1427# Compatibility for existing stop_XXXX() functions
1428# Stop a service in screen
1429# If a PID is available use it, kill the whole process group via TERM
1430# If screen is being used kill the screen window; this will catch processes
1431# that did not leave a PID behind
1432# screen_stop service
1433function screen_stop {
1434 # Clean up the screen window
1435 stop_process $1
1436}
1437
1438
Sean Dague2c65e712014-12-18 09:44:56 -05001439# Plugin Functions
1440# =================
1441
1442DEVSTACK_PLUGINS=${DEVSTACK_PLUGINS:-""}
1443
1444# enable_plugin <name> <url> [branch]
1445#
1446# ``name`` is an arbitrary name - (aka: glusterfs, nova-docker, zaqar)
1447# ``url`` is a git url
1448# ``branch`` is a gitref. If it's not set, defaults to master
1449function enable_plugin {
1450 local name=$1
1451 local url=$2
1452 local branch=${3:-master}
1453 DEVSTACK_PLUGINS+=",$name"
1454 GITREPO[$name]=$url
1455 GITDIR[$name]=$DEST/$name
1456 GITBRANCH[$name]=$branch
1457}
1458
1459# fetch_plugins
1460#
1461# clones all plugins
1462function fetch_plugins {
1463 local plugins="${DEVSTACK_PLUGINS}"
1464 local plugin
1465
1466 # short circuit if nothing to do
1467 if [[ -z $plugins ]]; then
1468 return
1469 fi
1470
1471 echo "Fetching devstack plugins"
1472 for plugin in ${plugins//,/ }; do
1473 git_clone_by_name $plugin
1474 done
1475}
1476
1477# load_plugin_settings
1478#
1479# Load settings from plugins in the order that they were registered
1480function load_plugin_settings {
1481 local plugins="${DEVSTACK_PLUGINS}"
1482 local plugin
1483
1484 # short circuit if nothing to do
1485 if [[ -z $plugins ]]; then
1486 return
1487 fi
1488
1489 echo "Loading plugin settings"
1490 for plugin in ${plugins//,/ }; do
1491 local dir=${GITDIR[$plugin]}
1492 # source any known settings
1493 if [[ -f $dir/devstack/settings ]]; then
1494 source $dir/devstack/settings
1495 fi
1496 done
1497}
1498
1499# run_plugins
1500#
1501# Run the devstack/plugin.sh in all the plugin directories. These are
1502# run in registration order.
1503function run_plugins {
1504 local mode=$1
1505 local phase=$2
Bharat Kumar Kobagana441ff072015-01-08 12:26:26 +05301506
1507 local plugins="${DEVSTACK_PLUGINS}"
1508 local plugin
Sean Dague2c65e712014-12-18 09:44:56 -05001509 for plugin in ${plugins//,/ }; do
1510 local dir=${GITDIR[$plugin]}
1511 if [[ -f $dir/devstack/plugin.sh ]]; then
1512 source $dir/devstack/plugin.sh $mode $phase
1513 fi
1514 done
1515}
1516
1517function run_phase {
1518 local mode=$1
1519 local phase=$2
1520 if [[ -d $TOP_DIR/extras.d ]]; then
1521 for i in $TOP_DIR/extras.d/*.sh; do
1522 [[ -r $i ]] && source $i $mode $phase
1523 done
1524 fi
1525 # the source phase corresponds to settings loading in plugins
1526 if [[ "$mode" == "source" ]]; then
1527 load_plugin_settings
1528 else
1529 run_plugins $mode $phase
1530 fi
1531}
1532
Dean Troyerdff49a22014-01-30 15:37:40 -06001533
1534# Service Functions
1535# =================
1536
1537# remove extra commas from the input string (i.e. ``ENABLED_SERVICES``)
1538# _cleanup_service_list service-list
Ian Wienandaee18c72014-02-21 15:35:08 +11001539function _cleanup_service_list {
Dean Troyerdff49a22014-01-30 15:37:40 -06001540 echo "$1" | sed -e '
1541 s/,,/,/g;
1542 s/^,//;
1543 s/,$//
1544 '
1545}
1546
1547# disable_all_services() removes all current services
1548# from ``ENABLED_SERVICES`` to reset the configuration
1549# before a minimal installation
1550# Uses global ``ENABLED_SERVICES``
1551# disable_all_services
Ian Wienandaee18c72014-02-21 15:35:08 +11001552function disable_all_services {
Dean Troyerdff49a22014-01-30 15:37:40 -06001553 ENABLED_SERVICES=""
1554}
1555
1556# Remove all services starting with '-'. For example, to install all default
1557# services except rabbit (rabbit) set in ``localrc``:
1558# ENABLED_SERVICES+=",-rabbit"
1559# Uses global ``ENABLED_SERVICES``
1560# disable_negated_services
Ian Wienandaee18c72014-02-21 15:35:08 +11001561function disable_negated_services {
Dean Troyerdff49a22014-01-30 15:37:40 -06001562 local tmpsvcs="${ENABLED_SERVICES}"
1563 local service
1564 for service in ${tmpsvcs//,/ }; do
1565 if [[ ${service} == -* ]]; then
1566 tmpsvcs=$(echo ${tmpsvcs}|sed -r "s/(,)?(-)?${service#-}(,)?/,/g")
1567 fi
1568 done
1569 ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
1570}
1571
1572# disable_service() removes the services passed as argument to the
1573# ``ENABLED_SERVICES`` list, if they are present.
1574#
1575# For example:
1576# disable_service rabbit
1577#
1578# This function does not know about the special cases
1579# for nova, glance, and neutron built into is_service_enabled().
1580# Uses global ``ENABLED_SERVICES``
1581# disable_service service [service ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001582function disable_service {
Dean Troyerdff49a22014-01-30 15:37:40 -06001583 local tmpsvcs=",${ENABLED_SERVICES},"
1584 local service
1585 for service in $@; do
1586 if is_service_enabled $service; then
1587 tmpsvcs=${tmpsvcs//,$service,/,}
1588 fi
1589 done
1590 ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
1591}
1592
1593# enable_service() adds the services passed as argument to the
1594# ``ENABLED_SERVICES`` list, if they are not already present.
1595#
1596# For example:
1597# enable_service qpid
1598#
1599# This function does not know about the special cases
1600# for nova, glance, and neutron built into is_service_enabled().
1601# Uses global ``ENABLED_SERVICES``
1602# enable_service service [service ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001603function enable_service {
Dean Troyerdff49a22014-01-30 15:37:40 -06001604 local tmpsvcs="${ENABLED_SERVICES}"
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001605 local service
Dean Troyerdff49a22014-01-30 15:37:40 -06001606 for service in $@; do
1607 if ! is_service_enabled $service; then
1608 tmpsvcs+=",$service"
1609 fi
1610 done
1611 ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
1612 disable_negated_services
1613}
1614
1615# is_service_enabled() checks if the service(s) specified as arguments are
1616# enabled by the user in ``ENABLED_SERVICES``.
1617#
1618# Multiple services specified as arguments are ``OR``'ed together; the test
1619# is a short-circuit boolean, i.e it returns on the first match.
1620#
1621# There are special cases for some 'catch-all' services::
1622# **nova** returns true if any service enabled start with **n-**
1623# **cinder** returns true if any service enabled start with **c-**
1624# **ceilometer** returns true if any service enabled start with **ceilometer**
1625# **glance** returns true if any service enabled start with **g-**
1626# **neutron** returns true if any service enabled start with **q-**
1627# **swift** returns true if any service enabled start with **s-**
1628# **trove** returns true if any service enabled start with **tr-**
1629# For backward compatibility if we have **swift** in ENABLED_SERVICES all the
1630# **s-** services will be enabled. This will be deprecated in the future.
1631#
1632# Cells within nova is enabled if **n-cell** is in ``ENABLED_SERVICES``.
1633# We also need to make sure to treat **n-cell-region** and **n-cell-child**
1634# as enabled in this case.
1635#
1636# Uses global ``ENABLED_SERVICES``
1637# is_service_enabled service [service ...]
Ian Wienandaee18c72014-02-21 15:35:08 +11001638function is_service_enabled {
Sean Dague45917cc2014-02-24 16:09:14 -05001639 local xtrace=$(set +o | grep xtrace)
1640 set +o xtrace
1641 local enabled=1
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001642 local services=$@
1643 local service
Dean Troyerdff49a22014-01-30 15:37:40 -06001644 for service in ${services}; do
Sean Dague45917cc2014-02-24 16:09:14 -05001645 [[ ,${ENABLED_SERVICES}, =~ ,${service}, ]] && enabled=0
Dean Troyerdff49a22014-01-30 15:37:40 -06001646
1647 # Look for top-level 'enabled' function for this service
1648 if type is_${service}_enabled >/dev/null 2>&1; then
1649 # A function exists for this service, use it
1650 is_${service}_enabled
Sean Dague45917cc2014-02-24 16:09:14 -05001651 enabled=$?
Dean Troyerdff49a22014-01-30 15:37:40 -06001652 fi
1653
1654 # TODO(dtroyer): Remove these legacy special-cases after the is_XXX_enabled()
1655 # are implemented
1656
Sean Dague45917cc2014-02-24 16:09:14 -05001657 [[ ${service} == n-cell-* && ${ENABLED_SERVICES} =~ "n-cell" ]] && enabled=0
Chris Dent2f27a0e2014-09-09 13:46:02 +01001658 [[ ${service} == n-cpu-* && ${ENABLED_SERVICES} =~ "n-cpu" ]] && enabled=0
Sean Dague45917cc2014-02-24 16:09:14 -05001659 [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && enabled=0
1660 [[ ${service} == "cinder" && ${ENABLED_SERVICES} =~ "c-" ]] && enabled=0
1661 [[ ${service} == "ceilometer" && ${ENABLED_SERVICES} =~ "ceilometer-" ]] && enabled=0
1662 [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && enabled=0
1663 [[ ${service} == "ironic" && ${ENABLED_SERVICES} =~ "ir-" ]] && enabled=0
1664 [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && enabled=0
1665 [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && enabled=0
1666 [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && enabled=0
1667 [[ ${service} == s-* && ${ENABLED_SERVICES} =~ "swift" ]] && enabled=0
Dean Troyerdff49a22014-01-30 15:37:40 -06001668 done
Sean Dague45917cc2014-02-24 16:09:14 -05001669 $xtrace
1670 return $enabled
Dean Troyerdff49a22014-01-30 15:37:40 -06001671}
1672
1673# Toggle enable/disable_service for services that must run exclusive of each other
1674# $1 The name of a variable containing a space-separated list of services
1675# $2 The name of a variable in which to store the enabled service's name
1676# $3 The name of the service to enable
1677function use_exclusive_service {
1678 local options=${!1}
1679 local selection=$3
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001680 local out=$2
Dean Troyerdff49a22014-01-30 15:37:40 -06001681 [ -z $selection ] || [[ ! "$options" =~ "$selection" ]] && return 1
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001682 local opt
Dean Troyerdff49a22014-01-30 15:37:40 -06001683 for opt in $options;do
1684 [[ "$opt" = "$selection" ]] && enable_service $opt || disable_service $opt
1685 done
1686 eval "$out=$selection"
1687 return 0
1688}
1689
1690
Masayuki Igawaf6368d32014-02-20 13:31:26 +09001691# System Functions
1692# ================
Dean Troyerdff49a22014-01-30 15:37:40 -06001693
1694# Only run the command if the target file (the last arg) is not on an
1695# NFS filesystem.
Ian Wienandaee18c72014-02-21 15:35:08 +11001696function _safe_permission_operation {
Sean Dague45917cc2014-02-24 16:09:14 -05001697 local xtrace=$(set +o | grep xtrace)
1698 set +o xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -06001699 local args=( $@ )
1700 local last
1701 local sudo_cmd
1702 local dir_to_check
1703
1704 let last="${#args[*]} - 1"
1705
Dean Troyerd5dfa4c2014-07-25 11:13:11 -05001706 local dir_to_check=${args[$last]}
Dean Troyerdff49a22014-01-30 15:37:40 -06001707 if [ ! -d "$dir_to_check" ]; then
1708 dir_to_check=`dirname "$dir_to_check"`
1709 fi
1710
1711 if is_nfs_directory "$dir_to_check" ; then
Sean Dague45917cc2014-02-24 16:09:14 -05001712 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -06001713 return 0
1714 fi
1715
1716 if [[ $TRACK_DEPENDS = True ]]; then
1717 sudo_cmd="env"
1718 else
1719 sudo_cmd="sudo"
1720 fi
1721
Sean Dague45917cc2014-02-24 16:09:14 -05001722 $xtrace
Dean Troyerdff49a22014-01-30 15:37:40 -06001723 $sudo_cmd $@
1724}
1725
1726# Exit 0 if address is in network or 1 if address is not in network
1727# ip-range is in CIDR notation: 1.2.3.4/20
1728# address_in_net ip-address ip-range
Ian Wienandaee18c72014-02-21 15:35:08 +11001729function address_in_net {
Dean Troyerdff49a22014-01-30 15:37:40 -06001730 local ip=$1
1731 local range=$2
1732 local masklen=${range#*/}
1733 local network=$(maskip ${range%/*} $(cidr2netmask $masklen))
1734 local subnet=$(maskip $ip $(cidr2netmask $masklen))
1735 [[ $network == $subnet ]]
1736}
1737
1738# Add a user to a group.
1739# add_user_to_group user group
Ian Wienandaee18c72014-02-21 15:35:08 +11001740function add_user_to_group {
Dean Troyerdff49a22014-01-30 15:37:40 -06001741 local user=$1
1742 local group=$2
1743
1744 if [[ -z "$os_VENDOR" ]]; then
1745 GetOSVersion
1746 fi
1747
1748 # SLE11 and openSUSE 12.2 don't have the usual usermod
1749 if ! is_suse || [[ "$os_VENDOR" = "openSUSE" && "$os_RELEASE" != "12.2" ]]; then
1750 sudo usermod -a -G "$group" "$user"
1751 else
1752 sudo usermod -A "$group" "$user"
1753 fi
1754}
1755
1756# Convert CIDR notation to a IPv4 netmask
1757# cidr2netmask cidr-bits
Ian Wienandaee18c72014-02-21 15:35:08 +11001758function cidr2netmask {
Dean Troyerdff49a22014-01-30 15:37:40 -06001759 local maskpat="255 255 255 255"
1760 local maskdgt="254 252 248 240 224 192 128"
1761 set -- ${maskpat:0:$(( ($1 / 8) * 4 ))}${maskdgt:$(( (7 - ($1 % 8)) * 4 )):3}
1762 echo ${1-0}.${2-0}.${3-0}.${4-0}
1763}
1764
1765# Gracefully cp only if source file/dir exists
1766# cp_it source destination
1767function cp_it {
1768 if [ -e $1 ] || [ -d $1 ]; then
1769 cp -pRL $1 $2
1770 fi
1771}
1772
1773# HTTP and HTTPS proxy servers are supported via the usual environment variables [1]
1774# ``http_proxy``, ``https_proxy`` and ``no_proxy``. They can be set in
1775# ``localrc`` or on the command line if necessary::
1776#
1777# [1] http://www.w3.org/Daemon/User/Proxies/ProxyClients.html
1778#
1779# http_proxy=http://proxy.example.com:3128/ no_proxy=repo.example.net ./stack.sh
1780
Ian Wienandaee18c72014-02-21 15:35:08 +11001781function export_proxy_variables {
Sean Dague53753292014-12-04 19:38:15 -05001782 if isset http_proxy ; then
Dean Troyerdff49a22014-01-30 15:37:40 -06001783 export http_proxy=$http_proxy
1784 fi
Sean Dague53753292014-12-04 19:38:15 -05001785 if isset https_proxy ; then
Dean Troyerdff49a22014-01-30 15:37:40 -06001786 export https_proxy=$https_proxy
1787 fi
Sean Dague53753292014-12-04 19:38:15 -05001788 if isset no_proxy ; then
Dean Troyerdff49a22014-01-30 15:37:40 -06001789 export no_proxy=$no_proxy
1790 fi
1791}
1792
1793# Returns true if the directory is on a filesystem mounted via NFS.
Ian Wienandaee18c72014-02-21 15:35:08 +11001794function is_nfs_directory {
Dean Troyerdff49a22014-01-30 15:37:40 -06001795 local mount_type=`stat -f -L -c %T $1`
1796 test "$mount_type" == "nfs"
1797}
1798
1799# Return the network portion of the given IP address using netmask
1800# netmask is in the traditional dotted-quad format
1801# maskip ip-address netmask
Ian Wienandaee18c72014-02-21 15:35:08 +11001802function maskip {
Dean Troyerdff49a22014-01-30 15:37:40 -06001803 local ip=$1
1804 local mask=$2
1805 local l="${ip%.*}"; local r="${ip#*.}"; local n="${mask%.*}"; local m="${mask#*.}"
1806 local subnet=$((${ip%%.*}&${mask%%.*})).$((${r%%.*}&${m%%.*})).$((${l##*.}&${n##*.})).$((${ip##*.}&${mask##*.}))
1807 echo $subnet
1808}
1809
1810# Service wrapper to restart services
1811# restart_service service-name
Ian Wienandaee18c72014-02-21 15:35:08 +11001812function restart_service {
Dean Troyerdff49a22014-01-30 15:37:40 -06001813 if is_ubuntu; then
1814 sudo /usr/sbin/service $1 restart
1815 else
1816 sudo /sbin/service $1 restart
1817 fi
1818}
1819
1820# Only change permissions of a file or directory if it is not on an
1821# NFS filesystem.
Ian Wienandaee18c72014-02-21 15:35:08 +11001822function safe_chmod {
Dean Troyerdff49a22014-01-30 15:37:40 -06001823 _safe_permission_operation chmod $@
1824}
1825
1826# Only change ownership of a file or directory if it is not on an NFS
1827# filesystem.
Ian Wienandaee18c72014-02-21 15:35:08 +11001828function safe_chown {
Dean Troyerdff49a22014-01-30 15:37:40 -06001829 _safe_permission_operation chown $@
1830}
1831
1832# Service wrapper to start services
1833# start_service service-name
Ian Wienandaee18c72014-02-21 15:35:08 +11001834function start_service {
Dean Troyerdff49a22014-01-30 15:37:40 -06001835 if is_ubuntu; then
1836 sudo /usr/sbin/service $1 start
1837 else
1838 sudo /sbin/service $1 start
1839 fi
1840}
1841
1842# Service wrapper to stop services
1843# stop_service service-name
Ian Wienandaee18c72014-02-21 15:35:08 +11001844function stop_service {
Dean Troyerdff49a22014-01-30 15:37:40 -06001845 if is_ubuntu; then
1846 sudo /usr/sbin/service $1 stop
1847 else
1848 sudo /sbin/service $1 stop
1849 fi
1850}
1851
1852
1853# Restore xtrace
1854$XTRACE
1855
1856# Local variables:
1857# mode: shell-script
1858# End: