Allow skipping exercises.

- Catch a special exit signal 55 to notify that we want to skip an
  excercise.
- Move is_enabled_service to functions.
- Fix bug 928390.

Change-Id: Iebf7a6f30a0f305a2a70173fb6b988bc07e34292
diff --git a/HACKING.rst b/HACKING.rst
index a105a66..7262cff 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -136,6 +136,10 @@
     FLOATING_IP=`euca-allocate-address | cut -f2`
     die_if_not_set FLOATING_IP "Failure allocating floating IP"
 
+* If you want an exercise to be skipped when for example a service wasn't
+  enabled for the exercise to be run, you can exit your exercise with the
+  special exitcode 55 and it will be detected as skipped.
+
 * The exercise scripts should only use the various OpenStack client binaries to
   interact with OpenStack.  This specifically excludes any ``*-manage`` tools
   as those assume direct access to configuration and databases, as well as direct
diff --git a/exercise.sh b/exercise.sh
index 2072b23..15f264f 100755
--- a/exercise.sh
+++ b/exercise.sh
@@ -32,7 +32,10 @@
         echo Running $script
         echo "====================================================================="
         $EXERCISE_DIR/$script.sh
-        if [[ $? -ne 0 ]] ; then
+        exitcode=$?
+        if [[ $exitcode == 55 ]]; then
+            skips="$skips $script"
+        elif [[ $exitcode -ne 0 ]] ; then
             failures="$failures $script"
         else
             passes="$passes $script"
diff --git a/exercises/swift.sh b/exercises/swift.sh
index d8b41a3..732445d 100755
--- a/exercises/swift.sh
+++ b/exercises/swift.sh
@@ -36,6 +36,9 @@
 # Container name
 CONTAINER=ex-swift
 
+# If swift is not enabled we exit with exitcode 55 which mean
+# exercise is skipped.
+is_service_enabled swift || exit 55
 
 # Testing Swift
 # =============
diff --git a/functions b/functions
index 7fd37c0..75c20d7 100644
--- a/functions
+++ b/functions
@@ -115,6 +115,28 @@
 }
 
 
+# is_service_enabled() checks if the service(s) specified as arguments are
+# enabled by the user in **ENABLED_SERVICES**.
+#
+# If there are multiple services specified as arguments the test performs a
+# boolean OR or if any of the services specified on the command line
+# return true.
+#
+# There is a special cases for some 'catch-all' services::
+#   **nova** returns true if any service enabled start with **n-**
+#   **glance** returns true if any service enabled start with **g-**
+#   **quantum** returns true if any service enabled start with **q-**
+function is_service_enabled() {
+    services=$@
+    for service in ${services}; do
+        [[ ,${ENABLED_SERVICES}, =~ ,${service}, ]] && return 0
+        [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && return 0
+        [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && return 0
+        [[ ${service} == "quantum" && ${ENABLED_SERVICES} =~ "q-" ]] && return 0
+    done
+    return 1
+}
+
 
 # Test if the named environment variable is set and not zero length
 # is_set env-var
@@ -151,4 +173,4 @@
 }
 
 # Restore xtrace
-$XTRACE
\ No newline at end of file
+$XTRACE
diff --git a/stack.sh b/stack.sh
index d77b1d5..3a7fc5d 100755
--- a/stack.sh
+++ b/stack.sh
@@ -268,30 +268,6 @@
     set -o xtrace
 }
 
-# is_service_enabled() checks if the service(s) specified as arguments are
-# enabled by the user in **ENABLED_SERVICES**.
-#
-# If there are multiple services specified as arguments the test performs a
-# boolean OR or if any of the services specified on the command line
-# return true.
-#
-# There is a special cases for some 'catch-all' services::
-#   **nova** returns true if any service enabled start with **n-**
-#   **glance** returns true if any service enabled start with **g-**
-#   **quantum** returns true if any service enabled start with **q-**
-
-function is_service_enabled() {
-    services=$@
-    for service in ${services}; do
-        [[ ,${ENABLED_SERVICES}, =~ ,${service}, ]] && return 0
-        [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && return 0
-        [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && return 0
-        [[ ${service} == "quantum" && ${ENABLED_SERVICES} =~ "q-" ]] && return 0
-    done
-    return 1
-}
-
-
 # Nova Network Configuration
 # --------------------------