5
5
"errors"
6
6
"fmt"
7
7
"io"
8
+ "io/ioutil"
8
9
"math/rand"
9
10
"net"
10
11
"strconv"
@@ -28,16 +29,26 @@ const (
28
29
// The output of the script is the name of a file containing the PID for the started daemon
29
30
startDaemonScript = `set -e
30
31
TMPDIR=${TMPDIR:-/tmp}
31
- CONFIGFILE=$(mktemp 2> /dev/null || ( echo -n "" > ${TMPDIR}/%[1]s && echo ${TMPDIR}/%[1]s) )
32
- PIDFILE=$(mktemp 2> /dev/null || ( echo -n "" > ${TMPDIR}/%[2]s && echo ${TMPDIR}/%[2]s) )
32
+ CONFIGFILE=$(echo -n "" > ${TMPDIR}/%[1]s && echo ${TMPDIR}/%[1]s)
33
+ PIDFILE=$(echo -n "" > ${TMPDIR}/%[2]s && echo ${TMPDIR}/%[2]s)
33
34
rm $PIDFILE
34
35
printf "pid file = ${PIDFILE}\n[root]\n path = /\n use chroot = no\n read only = no" > $CONFIGFILE
35
- rsync --daemon --config=${CONFIGFILE} --port=%[3]d
36
- echo ${PIDFILE}
36
+ rsync --no-detach --daemon --config=${CONFIGFILE} --port=%[3]d
37
37
`
38
- portRangeFrom = 30000
39
- portRangeTo = 60000
40
- remoteLabel = "root"
38
+ killDaemonScript = `set -e
39
+ TMPDIR=${TMPDIR:-/tmp}
40
+ PIDFILE=${TMPDIR}/%[1]s
41
+ kill $(cat ${PIDFILE})
42
+ `
43
+ checkDaemonScript = `set -e
44
+ TMPDIR=${TMPDIR:-/tmp}
45
+ PIDFILE=${TMPDIR}/%[1]s
46
+ ls ${PIDFILE}
47
+ `
48
+ portRangeFrom = 30000
49
+ portRangeTo = 60000
50
+ remoteLabel = "root"
51
+ RsyncDaemonStartTimeOut = 10 * time .Second
41
52
)
42
53
43
54
var (
@@ -152,26 +163,44 @@ func (s *rsyncDaemonStrategy) startRemoteDaemon() error {
152
163
}
153
164
cmdOut := & bytes.Buffer {}
154
165
cmdErr := & bytes.Buffer {}
155
- cmdIn := bytes .NewBufferString (fmt .Sprintf (startDaemonScript , krand .String (32 ), krand .String (32 ), port ))
156
- err = s .RemoteExecutor .Execute ([]string {"sh" }, cmdIn , cmdOut , cmdErr )
157
- if err != nil {
158
- glog .V (1 ).Infof ("Error starting rsync daemon: %v. Out: %s, Err: %s\n " , err , cmdOut .String (), cmdErr .String ())
159
- // Determine whether rsync is present in the container
160
- if checkRsync (s .RemoteExecutor ) != nil {
161
- return strategySetupError ("rsync not available in container" )
166
+ pidFile := krand .String (32 )
167
+ configFile := krand .String (32 )
168
+ cmdIn := bytes .NewBufferString (fmt .Sprintf (startDaemonScript , configFile , pidFile , port ))
169
+ daemonErr := make (chan error , 1 )
170
+ go func () {
171
+ err = s .RemoteExecutor .Execute ([]string {"sh" }, cmdIn , cmdOut , cmdErr )
172
+ if err != nil {
173
+ daemonErr <- fmt .Errorf ("error starting rsync daemon: %v\n Out: %s\n Err: %s\n " , err , cmdOut .String (), cmdErr .String ())
162
174
}
163
- return err
175
+ }()
176
+ // Wait until a pid file is present or an error has occurred
177
+ checkScript := bytes .NewBufferString (fmt .Sprintf (checkDaemonScript , pidFile ))
178
+ startTime := time .Now ()
179
+ for {
180
+ if time .Since (startTime ) > RsyncDaemonStartTimeOut {
181
+ return fmt .Errorf ("Timed out waiting for rsync daemon to start" )
182
+ }
183
+ checkScript .Reset ()
184
+ err = s .RemoteExecutor .Execute ([]string {"sh" }, checkScript , ioutil .Discard , ioutil .Discard )
185
+ if err == nil {
186
+ break
187
+ }
188
+ if len (daemonErr ) > 0 {
189
+ return <- daemonErr
190
+ }
191
+ time .Sleep (100 * time .Millisecond )
164
192
}
165
193
s .daemonPort = port
166
- s .daemonPIDFile = strings . TrimSpace ( cmdOut . String ())
194
+ s .daemonPIDFile = pidFile
167
195
return nil
168
196
}
169
197
170
198
func (s * rsyncDaemonStrategy ) killRemoteDaemon () error {
171
- cmd := []string {"sh" , "-c" , fmt .Sprintf ("kill $(cat %s)" , s .daemonPIDFile )}
199
+ cmd := []string {"sh" }
200
+ cmdIn := bytes .NewBufferString (fmt .Sprintf (killDaemonScript , s .daemonPIDFile ))
172
201
cmdOut := & bytes.Buffer {}
173
202
cmdErr := & bytes.Buffer {}
174
- err := s .RemoteExecutor .Execute (cmd , nil , cmdOut , cmdErr )
203
+ err := s .RemoteExecutor .Execute (cmd , cmdIn , cmdOut , cmdErr )
175
204
if err != nil {
176
205
glog .V (1 ).Infof ("Error killing rsync daemon: %v. Out: %s, Err: %s\n " , err , cmdOut .String (), cmdErr .String ())
177
206
}
0 commit comments