Browse code

Add run_process() to start services without screen

* USE_SCREEN defaults to True, set it to False to exec the services
directly via bash. SCREEN_DEV is still supported until the CI
scripts get updated.
* The extra logging file descriptors are properly closed in the child process
and stdout/stderr are redirected to the log files.
* The screen_rc() call is still present; this means that stack-screenrc will
have a complete record of what was started and rejoin-stack.sh may be able
to re-create the setup under screen.
* The python interpreter was unwilling to write to the log files without
unbufering stdout by using PYTHONUNBUFFERED. This feels hackish and should
be investigated further.

Change-Id: I012ed049f2c8b185a2e6929d73edc29e167bc21f

Dean Troyer authored on 2013/02/28 10:00:39
Showing 3 changed files
... ...
@@ -735,26 +735,69 @@ function restart_service() {
735 735
 }
736 736
 
737 737
 
738
+# _run_process() is designed to be backgrounded by run_process() to simulate a
739
+# fork.  It includes the dirty work of closing extra filehandles and preparing log
740
+# files to produce the same logs as screen_it().  The log filename is derived
741
+# from the service name and global-and-now-misnamed SCREEN_LOGDIR
742
+# _run_process service "command-line"
743
+function _run_process() {
744
+    local service=$1
745
+    local command="$2"
746
+
747
+    # Undo logging redirections and close the extra descriptors
748
+    exec 1>&3
749
+    exec 2>&3
750
+    exec 3>&-
751
+    exec 6>&-
752
+
753
+    if [[ -n ${SCREEN_LOGDIR} ]]; then
754
+        exec 1>&${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log 2>&1
755
+        ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
756
+
757
+        # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
758
+        export PYTHONUNBUFFERED=1
759
+    fi
760
+
761
+    exec /bin/bash -c "$command"
762
+    die "$service exec failure: $command"
763
+}
764
+
765
+
766
+# run_process() launches a child process that closes all file descriptors and
767
+# then exec's the passed in command.  This is meant to duplicate the semantics
768
+# of screen_it() without screen.  PIDs are written to
769
+# $SERVICE_DIR/$SCREEN_NAME/$service.pid
770
+# run_process service "command-line"
771
+function run_process() {
772
+    local service=$1
773
+    local command="$2"
774
+
775
+    # Spawn the child process
776
+    _run_process "$service" "$command" &
777
+    echo $!
778
+}
779
+
780
+
738 781
 # Helper to launch a service in a named screen
739 782
 # screen_it service "command-line"
740 783
 function screen_it {
741 784
     SCREEN_NAME=${SCREEN_NAME:-stack}
742 785
     SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
743
-    SCREEN_DEV=`trueorfalse True $SCREEN_DEV`
786
+    USE_SCREEN=$(trueorfalse True $USE_SCREEN)
744 787
 
745 788
     if is_service_enabled $1; then
746 789
         # Append the service to the screen rc file
747 790
         screen_rc "$1" "$2"
748 791
 
749
-        screen -S $SCREEN_NAME -X screen -t $1
792
+        if [[ "$USE_SCREEN" = "True" ]]; then
793
+            screen -S $SCREEN_NAME -X screen -t $1
750 794
 
751
-        if [[ -n ${SCREEN_LOGDIR} ]]; then
752
-            screen -S $SCREEN_NAME -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
753
-            screen -S $SCREEN_NAME -p $1 -X log on
754
-            ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
755
-        fi
795
+            if [[ -n ${SCREEN_LOGDIR} ]]; then
796
+                screen -S $SCREEN_NAME -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
797
+                screen -S $SCREEN_NAME -p $1 -X log on
798
+                ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
799
+            fi
756 800
 
757
-        if [[ "$SCREEN_DEV" = "True" ]]; then
758 801
             # sleep to allow bash to be ready to be send the command - we are
759 802
             # creating a new window in screen and then sends characters, so if
760 803
             # bash isn't running by the time we send the command, nothing happens
... ...
@@ -763,7 +806,8 @@ function screen_it {
763 763
             NL=`echo -ne '\015'`
764 764
             screen -S $SCREEN_NAME -p $1 -X stuff "$2 || touch \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL"
765 765
         else
766
-            screen -S $SCREEN_NAME -p $1 -X exec /bin/bash -c "$2 || touch \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\""
766
+            # Spawn directly without screen
767
+            run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$service.pid
767 768
         fi
768 769
     fi
769 770
 }
... ...
@@ -824,8 +824,17 @@ fi
824 824
 # Configure screen
825 825
 # ----------------
826 826
 
827
-if [ -z "$SCREEN_HARDSTATUS" ]; then
828
-    SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})'
827
+USE_SCREEN=$(trueorfalse True $USE_SCREEN)
828
+if [[ "$USE_SCREEN" == "True" ]]; then
829
+    # Create a new named screen to run processes in
830
+    screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash
831
+    sleep 1
832
+
833
+    # Set a reasonable status bar
834
+    if [ -z "$SCREEN_HARDSTATUS" ]; then
835
+        SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})'
836
+    fi
837
+    screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS"
829 838
 fi
830 839
 
831 840
 # Clear screen rc file
... ...
@@ -834,12 +843,6 @@ if [[ -e $SCREENRC ]]; then
834 834
     echo -n > $SCREENRC
835 835
 fi
836 836
 
837
-# Create a new named screen to run processes in
838
-screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash
839
-sleep 1
840
-
841
-# Set a reasonable status bar
842
-screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS"
843 837
 
844 838
 # Initialize the directory for service status check
845 839
 init_service_check
... ...
@@ -30,8 +30,8 @@ NOVA_ENABLED_APIS=ec2,osapi_compute,metadata
30 30
 # stuffing text into the screen windows so that a developer can use
31 31
 # ctrl-c, up-arrow, enter to restart the service. Starting services
32 32
 # this way is slightly unreliable, and a bit slower, so this can
33
-# be disabled for automated testing by setting this value to false.
34
-SCREEN_DEV=True
33
+# be disabled for automated testing by setting this value to False.
34
+USE_SCREEN=True
35 35
 
36 36
 # Repositories
37 37
 # ------------
... ...
@@ -198,3 +198,6 @@ VOLUME_BACKING_FILE_SIZE=${VOLUME_BACKING_FILE_SIZE:-5130M}
198 198
 
199 199
 PRIVATE_NETWORK_NAME=${PRIVATE_NETWORK_NAME:-"private"}
200 200
 PUBLIC_NETWORK_NAME=${PUBLIC_NETWORK_NAME:-"nova"}
201
+
202
+# Compatibility until it's eradicated from CI
203
+USE_SCREEN=${SCREEN_DEV:-$USE_SCREEN}