Merge lp:~nijaba/charm-tools/peer-replay into lp:~charmers/charm-tools/trunk

Proposed by Nick Barcet on 2011-12-22
Status: Merged
Approved by: Clint Byrum on 2012-01-11
Approved revision: 130
Merged at revision: 114
Proposed branch: lp:~nijaba/charm-tools/peer-replay
Merge into: lp:~charmers/charm-tools/trunk
Diff against target: 794 lines (+539/-97)
2 files modified
helpers/sh/peer.sh (+377/-84)
tests/helpers/test_peer.sh (+162/-13)
To merge this branch: bzr merge lp:~nijaba/charm-tools/peer-replay
Reviewer Review Type Date Requested Status
Clint Byrum (community) Approve on 2012-01-11
Nick Barcet (community) Resubmit on 2012-01-06
Review via email: mp+86721@code.launchpad.net

Commit Message

Adds 3 new features:
 * the possibility to do a ch_peer_[rsync|scp] outside of a peer relation (typically in a config-changed event) once at least one copy has been done within the peer relation. The copy will be done from the leader to all hosts to which it has done copies to previously
 * the possibility to do a ch_peer_copy_replay which will redo all copies (scp or rsync) done previously to all hosts (typically in a config-changed event)
 * ch_peer_copy_cleanup <remote-unit> which should be called every time there is a peer-relation-departed event received to remove the unit from the host cache.

Description of the Change

A big commit which adds:
 * the possibility to do a ch_peer_[rsync|scp] outside of a peer relation (typically in a config-changed event) once at least one copy has been done within the peer relation. The copy will be done from the leader to all hosts to which it has done copies to previously
 * the possibility to do a ch_peer_copy_replay which will redo all copies (scp or rsync) done previously to all hosts (typically in a config-changed event)
 * ch_peer_copy_cleanup <remote-unit> which should be called every time there is a peer-relation-departed event received to remove the unit from the host cache.

This branch assumes that lp:~nijaba/charm-tools/buildd-fixes has been merged already.

To post a comment you must log in.
lp:~nijaba/charm-tools/peer-replay updated on 2011-12-23
112. By Nick Barcet on 2011-12-23

merging with buildd-fixes-part-deux

113. By Nick Barcet on 2011-12-23

fixes after API change

Nick Barcet (nijaba) wrote :

Now using the new API and changes from buildd-fixes-part-deux

review: Resubmit
lp:~nijaba/charm-tools/peer-replay updated on 2012-01-05
114. By Nick Barcet on 2012-01-04

ensure proper return results

115. By Nick Barcet on 2012-01-04

rebasing from trunk

116. By Nick Barcet on 2012-01-04

juju sets home to /home/ubuntu while user is root :(

117. By Nick Barcet on 2012-01-04

better test of ch_peer_copy_new

118. By Nick Barcet on 2012-01-04

need to replace all instances of our host place holder...

119. By Nick Barcet on 2012-01-05

deal with shell expansion better, home dir and multiple files

120. By Nick Barcet on 2012-01-05

unbound variable testing and wrongly place local fix

121. By Nick Barcet on 2012-01-05

did not know -z was not protecting with set -u

122. By Nick Barcet on 2012-01-05

resync with trunk

Nick Barcet (nijaba) wrote :

Ok, this branch is now working great.

Clint Byrum (clint-fewbar) wrote :

Hi Nick! Some blockers first:

[0]

+set -eu

Don't mess with this in helpers. There's never a reason to turn it off inside your helpers either. The script author needs to make this distinction knowingly, otherwise their script may not be able to handle the extra rigor. That said, all tests should set -eu.

[1]

Changing PermitRootLogin seems like overstepping our bounds in a charm helper. Perhaps raise an error if its attempted, and a separate ch_sshd_config_set PermitRootLogin yes call would be better. I'm worried that users will be upset that we so willingly gave all boxes root on all other boxes. Another way to go is to just not allow this to be done at all, and always require the use of a non-root user for transfers... which is what I would prefer actually.

[2]

97 + set +f
198 + eval "$copy_command $scp_options $p1 $path"
199 + set -f

What if it was already +f? Now you just turned globbing back on.

Also why are you doing eval?

$copy_command $scp_options $p1 $path

should work fine. Also its not clear *why* you don't want globbing, so a comment would be useful here.

[3]

546 +ch_peer_rsync -p $CH_portnum -o "-azq" "$CH_TEMPDIR/sourcedir/*" "$CH_TEMPDIR/destdir/" ||
547 +chres=$?

If ch_peer_rsync returns 0, this will move on and fail because of the set -u, because the || is still open so we are saying "run ch_peer_rsync, OR chres=$?".

I would think the safest way to achieve what I think is the desired logic would be

if ch_peer_rsync ... ; then
  chres=0
else
  chres=$?
fi

Those are the blockers. The rest are nit picks, but should be fixed:

[4]

+ juju-log "_ch_peer_copy_set_paths"

Guessing you forgot -l DEBUG

[5]

+ if [ ! x`echo "$HOME" | grep "$USER"` = x"$HOME" ] ; then

use x$VAR or "$VAR" .. not both. The x is used when you don't want to use quotes for some reason.

[6]

+ if [ -z "$list" ] || [ x"$list" = x"" ] ; then

These conditions are redundant..

[7]

+ if [ ! -n "$copies" ] ; then

! -n is better expressed as -z

[8]

ch_peer_copy_cleanup is going to return the result of the sed command. Best add a 'return 0' if you want to ignore that result.

review: Needs Fixing
Nick Barcet (nijaba) wrote :
Download full text (3.4 KiB)

> [0]
>
> +set -eu
>
> Don't mess with this in helpers. There's never a reason to turn it off inside
> your helpers either. The script author needs to make this distinction
> knowingly, otherwise their script may not be able to handle the extra rigor.
> That said, all tests should set -eu.

fixed, thanks

> [1]
>
> Changing PermitRootLogin seems like overstepping our bounds in a charm helper.
> Perhaps raise an error if its attempted, and a separate ch_sshd_config_set
> PermitRootLogin yes call would be better. I'm worried that users will be upset
> that we so willingly gave all boxes root on all other boxes. Another way to go
> is to just not allow this to be done at all, and always require the use of a
> non-root user for transfers... which is what I would prefer actually.

ok, added ch_sshd_set_root_login [0|1] function and a warning when user is root that encourages to use another user.

Small question: how would you use another user in a hook? use 'sudo ubuntu' in front of the command?

> [2]
>
> 97 + set +f
> 198 + eval "$copy_command $scp_options $p1 $path"
> 199 + set -f
>
> What if it was already +f? Now you just turned globbing back on.

You are absolutely right ! I now store the state and restore it at the end.

> Also why are you doing eval?
>
> $copy_command $scp_options $p1 $path
>
> should work fine.

Agree that it should but it is giving me a" Missing trailing-' in remote-shell command." when running the ch_peer_rsync test. This has something to do with the quote interpretation which I could only solve by using eval. suggestion welcome.

> Also its not clear *why* you don't want globbing, so a
> comment would be useful here.

I need to turn off globbing so that the $paths variable is not expanded when on the paths ends with a * for example, as my loop expect pairs of paths and this would be messed up otherwise. I added a comment to explain this.

> [3]
>
> 546 +ch_peer_rsync -p $CH_portnum -o "-azq" "$CH_TEMPDIR/sourcedir/*"
> "$CH_TEMPDIR/destdir/" ||
> 547 +chres=$?
>
> If ch_peer_rsync returns 0, this will move on and fail because of the set -u,
> because the || is still open so we are saying "run ch_peer_rsync, OR
> chres=$?".
>
> I would think the safest way to achieve what I think is the desired logic
> would be
>
> if ch_peer_rsync ... ; then
> chres=0
> else
> chres=$?
> fi

fixed, thanks

> Those are the blockers. The rest are nit picks, but should be fixed:
>
> [4]
>
> + juju-log "_ch_peer_copy_set_paths"
>
> Guessing you forgot -l DEBUG

This is a nice way to say I did not even know it existed....

> [5]
>
> + if [ ! x`echo "$HOME" | grep "$USER"` = x"$HOME" ] ; then
>
> use x$VAR or "$VAR" .. not both. The x is used when you don't want to use
> quotes for some reason.

Not according to http://stackoverflow.com/questions/174119/why-do-shell-script-comparisons-often-use-xvar-xyes and other refs I have ran across, but I agree this might be an overkill here.

> [6]
>
>
> + if [ -z "$list" ] || [ x"$list" = x"" ] ; then
>
> These conditions are redundant..

fixed, thanks. bad understanding of -z on my side, ttytt.

> [7]
>
> + if [...

Read more...

lp:~nijaba/charm-tools/peer-replay updated on 2012-01-06
123. By <email address hidden> on 2012-01-06

address comments from https://code.launchpad.net/~nijaba/charm-tools/peer-replay/+merge/86721/comments/189159

124. By Nick Barcet on 2012-01-06

adapt mock_juju_log to print all params received

125. By Nick Barcet on 2012-01-06

some logic and typo fixes

Nick Barcet (nijaba) wrote :

and now tested with multiple units

review: Resubmit
lp:~nijaba/charm-tools/peer-replay updated on 2012-01-09
126. By Nick Barcet on 2012-01-06

I thought I add removed this set -eu earlier...

127. By Nick Barcet on 2012-01-09

uneeded debug

128. By Nick Barcet on 2012-01-09

we have to assume that it's a file, even if it does not (yet) exist for future replay

129. By <email address hidden> on 2012-01-09

should not assume relation-list is sorted

130. By Nick Barcet on 2012-01-09

better logic and tests for peer leader functions

Clint Byrum (clint-fewbar) wrote :

Looks good Nick, please merge with a single commit message. :) Just so I'm clear what I mean:

bzr branch lp:charm-tools
cd charm-tools
bzr merge lp:~nijaba/charm-tools/peer-replay
bzr commit -m 'Adding peer-replay capability'
bzr push lp:charm-tools

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'helpers/sh/peer.sh'
2--- helpers/sh/peer.sh 2012-01-04 18:35:46 +0000
3+++ helpers/sh/peer.sh 2012-01-09 18:47:25 +0000
4@@ -26,13 +26,24 @@
5 {
6 local REMOTE_UNIT_ID=`ch_unit_id $JUJU_REMOTE_UNIT`
7 local LOCAL_UNIT_ID=`ch_my_unit_id`
8- local FIRST_UNIT=`relation-list | head -n 1`
9- local FIRST_UNIT_ID=`ch_unit_id $FIRST_UNIT`
10-
11- if [ $LOCAL_UNIT_ID -lt $REMOTE_UNIT_ID ] && [ $LOCAL_UNIT_ID -lt $FIRST_UNIT_ID ]; then
12- return 0
13+ local FIRST_UNIT_ID=`relation-list | cut -d/ -f2 | sort -n | head -n 1`
14+ if [ -z $FIRST_UNIT_ID ] ; then
15+ #no one else in the list, we are obviously the leader
16+ return 0
17+ fi
18+ if [ $REMOTE_UNIT_ID -lt $FIRST_UNIT_ID ] ; then
19+ #remote must be departing, lets not worry about it
20+ if [ $LOCAL_UNIT_ID -lt $FIRST_UNIT_ID ]; then
21+ return 0
22+ else
23+ return 1
24+ fi
25 else
26- return 1
27+ if [ $LOCAL_UNIT_ID -lt $REMOTE_UNIT_ID ] && [ $LOCAL_UNIT_ID -lt $FIRST_UNIT_ID ]; then
28+ return 0
29+ else
30+ return 1
31+ fi
32 fi
33 }
34
35@@ -48,15 +59,17 @@
36 {
37 if ch_peer_i_am_leader; then
38 # this is the leader, return our own unit name
39- local leader="$JUJU_UNIT_NAME"
40+ local leader_id=`ch_unit_id $JUJU_UNIT_NAME`
41+ local leader_name=$JUJU_UNIT_NAME
42 else
43 # this is a slave the leader is the head of the list
44- local leader="`relation-list | head -n 1`"
45+ local leader_id=`relation-list | cut -d/ -f2 | sort -n | head -n 1`
46+ local leader_name=`relation-list | grep "/$leader_id$"`
47 fi
48 if [ $# -gt 0 ] && [ "$1" = "--id" ]; then
49- echo "`ch_unit_id $leader`"
50+ echo $leader_id
51 else
52- echo "$leader"
53+ echo $leader_name
54 fi
55 }
56
57@@ -106,6 +119,7 @@
58 # 0 when the file is copied
59 # 1 when there was an error
60 # 100 when the file is not copied
61+# 101 files were sent from the leader
62 #
63 # This executes in multiple passes between the leader and each peer
64 #
65@@ -126,97 +140,137 @@
66 local USAGE="ERROR in $*
67 USAGE: ch_peer_scp [-r][-p <port>][-o \"<opt>\"] sourcepath1 destpath1 [... sourcepathN destpathN]
68 USAGE: ch_peer_rsync [-p <port>][-o \"<opt>\"] sourcepath1 destpath1 [... sourcepathN destpathN]"
69- if [ x"$USER" = x"root" ] ; then
70- #juju sets $HOME to /home/ubuntu while user is root :(
71- local ssh_key_p="/root/.ssh"
72- else
73- local ssh_key_p="$HOME/.ssh"
74- fi
75+ # $USER may not be set
76+ USER=${USER:-`whoami`}
77+ # $HOME may not be set
78+ if [ -z "${HOME:-}" ] ; then
79+ if [ "$USER" = "root" ] ; then
80+ HOME="/$USER"
81+ else
82+ HOME="/home/$USER"
83+ fi
84+ fi
85+ if ! echo "$HOME" | grep -q "$USER" ; then
86+ if [ "$USER" = "root" ] ; then
87+ HOME="/$USER"
88+ else
89+ HOME="/home/$USER"
90+ fi
91+ fi
92+ local ssh_key_p="$HOME/.ssh"
93 local result=100
94
95 if [ $# -eq 0 ]; then
96- juju-log "$USAGE"
97- juju-log "ch_peer_copy: please provide at least one argument (path)"
98+ juju-log -l ERROR "$USAGE"
99+ juju-log -l ERROR "ch_peer_copy: please provide at least one argument (path)"
100 return 1
101 fi
102+
103+ local scp_options="-o StrictHostKeyChecking=no -B"
104+ local rsync_options=""
105+ local paths=""
106+ local copy_command="scp"
107+
108+ while [ "$#" -gt 0 ];
109+ do
110+ case "$1" in
111+ "-r") # scp recure
112+ scp_options="$scp_options -r"
113+ shift
114+ ;;
115+ "-p") # port number
116+ shift
117+ scp_options="$scp_options -P $1"
118+ rsync_options="$rsync_options -e 'ssh -p $1 -o StrictHostKeyChecking=no'"
119+ shift
120+ ;;
121+ "-o") # passthrough option
122+ shift
123+ scp_options="$scp_options $1"
124+ rsync_options="$rsync_options $1"
125+
126+ shift
127+ ;;
128+ "--rsync") # rsync secure (-e ssh)
129+ copy_command="rsync"
130+ shift
131+ ;;
132+ "$0")
133+ shift
134+ ;;
135+ *) # should be a pair of file
136+ local sourcep="$1"
137+ shift
138+ paths="$paths $sourcep $USER@X0X0X0X0:$1"
139+ juju-log -l DEBUG "ch_peer_copy: paths found: $sourcep -> $1"
140+ shift
141+ ;;
142+ esac
143+ done
144+ if [ -z "$paths" ]; then
145+ juju-log -l ERROR "$USAGE"
146+ juju-log -l ERROR "ch_peer_copy: please provide at least one path"
147+ exit 1
148+ fi
149+ if [ x"$copy_command" = x"rsync" ]; then
150+ scp_options=$rsync_options
151+ fi
152+
153+ local list=""
154+ list=`relation-list`
155+ # if we are not in a relation, do ch_peer_copy_new
156+ if [ -z "${list:-}" ] ; then
157+ _ch_peer_copy_new "$copy_command $scp_options" "$paths"
158+ result=$?
159+ juju-log -l DEBUG "ch_peer_copy: returning $result"
160+ return $result
161+ fi
162
163 ## LEADER ##
164
165 if ch_peer_i_am_leader ; then
166- juju-log "ch_peer_copy: This is our leader"
167+ juju-log -l INFO "ch_peer_copy: This is our leader"
168
169 local remote=`relation-get scp-hostname`
170 local ssh_key_saved=`relation-get scp-ssh-key-saved`
171- if [ -z $remote ]; then
172- juju-log "ch_peer_copy: We do not have a remote hostname yet"
173+ if [ -z $remote ] || [ "$remote" = "0" ] ; then
174+ juju-log -l DEBUG "ch_peer_copy: We do not have a remote hostname yet"
175+ relation-set scp-copy-done=0
176 remote=0
177 fi
178-
179- local scp_options="-o StrictHostKeyChecking=no -B"
180- local rsync_options=""
181- local paths=""
182- local copy_command="scp"
183-
184- while [ "$#" -gt 0 ];
185- do
186- case "$1" in
187- "-r") # scp recure
188- scp_options="$scp_options -r"
189- shift
190- ;;
191- "-p") # port number
192- shift
193- scp_options="$scp_options -P $1"
194- rsync_options="$rsync_options -e 'ssh -p $1 -o StrictHostKeyChecking=no'"
195- shift
196- ;;
197- "-o") # passthrough option
198- shift
199- scp_options="$scp_options $1"
200- rsync_options="$rsync_options $1"
201- shift
202- ;;
203- "--rsync") # rsync secure (-e ssh)
204- copy_command="rsync"
205- shift
206- ;;
207- "$0")
208- shift
209- ;;
210- *) # should be a pair of file
211- if [ -e `echo "$1" | sed 's/\*$//'` ]; then
212- local sourcep="$1"
213- shift
214- paths="$paths $sourcep $USER@$remote:$1"
215- juju-log "ch_peer_copy: paths found: $sourcep -> $1"
216- else
217- juju-log "ch_peer_copy: unknown option, skipping: $1"
218- fi
219- shift
220- ;;
221- esac
222- done
223- if [ ! -n "$paths" ]; then
224- juju-log "$USAGE"
225- juju-log "ch_peer_copy: please provide at least one path"
226- return 1
227- fi
228
229 if [ -n $remote ]; then
230 # We know where to send file to
231
232 case $ssh_key_saved in
233- 1) # ssh keys have been save, let's copy
234- if [ x"$copy_command" = x"rsync" ]; then
235- scp_options="$rsync_options"
236- fi
237- juju-log "ch_peer_copy: $copy_command $scp_options $paths"
238- eval "$copy_command $scp_options $paths"
239+ 1) # ssh keys have been saved, let's copy
240+ paths=`echo "$paths" | sed "s/X0X0X0X0/$remote/g"`
241+ local p1=""
242+ #we do not want globbing in the loop as it would mess with the number of passes and we work on pairs
243+ local globstate=`set -o | grep "noglob" | grep -q off && echo "+f" || echo "-f"`
244+ set -f
245+ for path in $paths ; do
246+ if [ "$p1" != "" ] ; then
247+ juju-log -l INFO "ch_peer_copy: $copy_command $scp_options $p1 $path"
248+ #globbing is wanted here to handle
249+ set +f
250+ eval "$copy_command $scp_options $p1 $path"
251+ set -f
252+ p1=""
253+ else
254+ p1=$path
255+ fi
256+ done
257+ set $globstate
258 relation-set scp-copy-done=1
259+ #save host and paths for later use
260+ _ch_peer_copy_save "$copy_command" "$scp_options" "$remote" "$paths" "$JUJU_REMOTE_UNIT"
261+ juju-log -l DEBUG "ch_peer_copy: save done"
262+ result=101
263 ;;
264
265 *) # we need to first distribute our ssh key files
266- juju-log "ch_peer_copy: distributing ssh key"
267+ juju-log -l DEBUG "ch_peer_copy: distributing ssh key"
268 if [ ! -f "$ssh_key_p/id_rsa" ]; then
269 ssh-keygen -q -N '' -t rsa -b 2048 -f $ssh_key_p/id_rsa
270 fi
271@@ -229,13 +283,14 @@
272 ## REMOTE ##
273
274 else # Not the leader
275- juju-log "ch_peer_copy: This is a slave"
276+ juju-log -l INFO "ch_peer_copy: This is a slave"
277
278 local scp_copy_done=`relation-get scp-copy-done`
279 local scp_ssh_key="`relation-get scp-ssh-key`"
280+ relation-set scp-hostname=`unit-get private-address`
281
282 if [ -n "$scp_copy_done" ] && [ $scp_copy_done = 1 ]; then
283- juju-log "ch_peer_copy: copy done, thanks"
284+ juju-log -l DEBUG "ch_peer_copy: copy done, thanks"
285 result=0
286 else
287 if [ -n "$scp_ssh_key" ]; then
288@@ -243,21 +298,259 @@
289 mkdir -p $ssh_key_p
290 chmod 700 $ssh_key_p
291 if ! grep -q -F "$scp_ssh_key" $ssh_key_p/authorized_keys ; then
292- juju-log "ch_peer_copy: saving ssh key $scp_ssh_key"
293+ if [ "$USER" = "root" ] ; then
294+ # if we are root, need to ensure we can login
295+ if ! grep -q "^PermitRootLogin yes" /etc/ssh/sshd_config ; then
296+ juju-log -l ERROR "PermitRootLogin is not set to yes and you are root. Please use another user or call 'ch_sshd_set_root_login 1' first"
297+ return 1
298+ fi
299+ fi
300+ juju-log -l DEBUG "ch_peer_copy: saving ssh key $scp_ssh_key"
301 echo "$scp_ssh_key" >> $ssh_key_p/authorized_keys
302 relation-set scp-ssh-key-saved=1
303 else
304- juju-log "ch_peer_copy: ssh keys already saved, thanks"
305+ juju-log -l DEBUG "ch_peer_copy: ssh keys already saved, thanks"
306 relation-set scp-ssh-key-saved=1
307 fi
308 chmod 600 "$ssh_key_p/authorized_keys"
309 else
310- juju-log "ch_peer_copy: ssh_keys not set yet, later"
311- relation-set scp-hostname=`unit-get private-address`
312+ juju-log -l DEBUG "ch_peer_copy: ssh_keys not set yet, later"
313 fi
314 fi
315 fi
316+
317 juju-log "ch_peer_copy: returning: $result"
318 return $result
319 }
320
321+##
322+# ch_sshd_set_root_login [0|1]
323+#
324+# modify /etc/ssh/sshd_config to set PermitRootLogin and reload ssh server
325+#
326+# param
327+# 0 disable
328+# 1 enable (default)
329+#
330+# returns nothing
331+
332+ch_sshd_set_root_login() {
333+ local on=${1:-1}
334+ if [ $on = 1 ] ; then
335+ if ! grep -q "^PermitRootLogin yes" /etc/ssh/sshd_config ; then
336+ sed -i 's/PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config
337+ service ssh reload
338+ fi
339+ else
340+ if ! grep -q "^PermitRootLogin no" /etc/ssh/sshd_config ; then
341+ sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
342+ service ssh reload
343+ fi
344+ fi
345+ return 0
346+}
347+
348+_ch_peer_copy_set_paths() {
349+ juju-log -l DEBUG "_ch_peer_copy_set_paths"
350+ local unitname=""
351+ unitname=`echo $JUJU_UNIT_NAME | sed 's/\//-/g'`
352+ CH_PEER_COPY_P="/var/lib/juju/$unitname"
353+ if [ ! `mkdir -p $CH_PEER_COPY_P 2>/dev/null` ] ; then
354+ CH_PEER_COPY_P="$HOME/ch_test/$unitname"
355+ mkdir -p $CH_PEER_COPY_P
356+ fi
357+ CH_PEER_COPY_HOST_F="$CH_PEER_COPY_P/ch_peer_copy_hosts"
358+ CH_PEER_COPY_PATHS_F="$CH_PEER_COPY_P/ch_peer_copy_paths"
359+}
360+
361+# Save copy commands and host for later replay
362+_ch_peer_copy_save() {
363+ # $1 copy_command
364+ # $2 options
365+ # $3 remote host
366+ # $4 paths
367+ # $5 remote unit name
368+
369+ juju-log -l DEBUG "_ch_peer_copy_save: $*"
370+
371+ _ch_peer_copy_set_paths
372+
373+ #save paths
374+ local suffix=`echo "$1%$2" | base64 -w 0 `
375+ local paths=`echo "$4" | base64 -w 0`
376+ local do_save=1
377+
378+ juju-log -l DEBUG "_ch_peer_copy_save: $* in ${CH_PEER_COPY_PATHS_F}-$suffix"
379+
380+ if [ -e "${CH_PEER_COPY_PATHS_F}-$suffix" ]; then
381+ if grep -q -F "$paths" "${CH_PEER_COPY_PATHS_F}-$suffix" ; then
382+ do_save=0
383+ fi
384+ fi
385+ if [ $do_save = 1 ] ; then
386+ juju-log -l DEBUG "_ch_peer_copy_save: saving $paths in ${CH_PEER_COPY_PATHS_F}-$suffix"
387+ echo "$paths" >> ${CH_PEER_COPY_PATHS_F}-$suffix
388+ juju-log -l DEBUG "_ch_peer_copy_save: paths: saved"
389+ fi
390+ do_save=1
391+
392+
393+ #save hosts
394+ if [ -e "${CH_PEER_COPY_HOST_F}" ]; then
395+ if grep -q -F "$3" "${CH_PEER_COPY_HOST_F}" ; then
396+ do_save=0
397+ fi
398+ fi
399+ [ $do_save = 1 ] && echo "$5 $3" >> $CH_PEER_COPY_HOST_F
400+ juju-log -l DEBUG "_ch_peer_copy_save: host: $5 $3"
401+}
402+
403+# do a new copy when not called within a relation
404+# returns
405+# 1 when there was an error
406+# 100 when the file is not copied
407+# 101 when the file is sent from server
408+
409+_ch_peer_copy_new() {
410+ # $1 "$copy_command $scp_options"
411+ # $2 "$paths"
412+
413+ _ch_peer_copy_set_paths
414+ local result=100
415+ local hosts=""
416+ local paths=""
417+
418+ if [ -e "$CH_PEER_COPY_HOST_F" ] ; then
419+ hosts=`cat $CH_PEER_COPY_HOST_F | cut -d" " -f2`
420+
421+ for h in $hosts ;
422+ do
423+ paths=`echo "$2" | sed "s/X0X0X0X0/$h/"`
424+ local p1=""
425+ #we do not want globbing in the loop as it would mess with the number of passes and we work on pairs
426+ local globstate=`set -o | grep "noglob" | grep -q off && echo "+f" || echo "-f"`
427+ set -f
428+ for path in $paths ; do
429+ if [ "$p1" != "" ] ; then
430+ juju-log -l INFO "_ch_peer_copy_new: $1 $p1 $path"
431+ set +f
432+ eval "$1 $p1 $path"
433+ set -f
434+ p1=""
435+ else
436+ p1=$path
437+ fi
438+ done
439+ set $globstate
440+ result=101
441+ done
442+ else
443+ juju-log -l DEBUG "ch_peer_copy_new: no host cache yet"
444+ fi
445+ juju-log -l DEBUG "_ch_peer_copy_new: returning $result"
446+ return $result
447+}
448+
449+##
450+# ch_peer_copy_replay
451+#
452+# do a replay of all previous cached copies
453+# would typically be used within a config changed to resync
454+# files that might have been modified to all peers in the relation
455+#
456+# param none
457+#
458+# returns
459+# 0 when the file is copied
460+# 1 when there was an error
461+# 100 when the file is not copied
462+
463+ch_peer_copy_replay() {
464+ _ch_peer_copy_set_paths
465+ local result=100
466+ local hosts=""
467+ local copies=""
468+ local h=""
469+ local c=""
470+ local commandopt=""
471+ local list_paths=""
472+ local encp=""
473+ local mpath=""
474+
475+ if [ ! -e "$CH_PEER_COPY_HOST_F" ] ; then
476+ juju-log -l DEBUG "ch_peer_copy_replay: no host cache yet"
477+ result=1
478+ fi
479+
480+ if [ $result = 100 ]; then
481+ hosts=`cat $CH_PEER_COPY_HOST_F`
482+ copies=`ls ${CH_PEER_COPY_PATHS_F}-* | xargs -n1 basename`
483+
484+ if [ -z "$copies" ] ; then
485+ juju-log -l DEBUG "ch_peer_copy_replay: no command cache yet"
486+ result=1
487+ fi
488+ fi
489+
490+ if [ $result = 100 ]; then
491+ for h in $hosts ;
492+ do
493+
494+ for c in $copies ;
495+ do
496+ commandopt=`echo $c | cut -d- -f2 | base64 -d | sed 's/%/ /'`
497+ list_paths=`cat $CH_PEER_COPY_P/$c`
498+
499+ for encp in $list_paths ;
500+ do
501+ mpath=`echo $encp | base64 -d`
502+ local p1=""
503+ #we do not want globbing in the loop as it would mess with the number of passes and we work on pairs
504+ local globstate=`set -o | grep "noglob" | grep -q off && echo "+f" || echo "-f"`
505+ set -f
506+ for path in $mpath ; do
507+ if [ "$p1" != "" ] ; then
508+ juju-log -l INFO "ch_peer_copy_replay: $commandopt $p1 $path"
509+ set +f
510+ eval "$commandopt $p1 $path"
511+ set -f
512+ p1=""
513+ else
514+ p1=$path
515+ fi
516+ done
517+ set $globstate
518+ result=0
519+ done
520+
521+ done
522+
523+ done
524+ fi
525+ return $result
526+}
527+
528+##
529+# ch_peer_copy_cleanup <remote-unit>
530+#
531+# Removes a parting remote unit fron the host cache
532+# Should be called for each peer-relation-departed
533+#
534+# param
535+# <remote-unit> name of the remote unit
536+#
537+# returns nothing
538+
539+ch_peer_copy_cleanup() {
540+ juju-log -l DEBUG "ch_peer_copy_cleanup: $1"
541+ _ch_peer_copy_set_paths
542+ if [ ! -e "$CH_PEER_COPY_HOST_F" ] ; then
543+ juju-log -l DEBUG "ch_peer_copy_cleanup: no host cache yet"
544+ return
545+ fi
546+ local unitname=""
547+ unitname=`echo $1 | sed -e 's/\(\.\|\/\|\*\|\[\|\]\)/\\&/g'`
548+ sed -i "/^$unitname.*$/d" $CH_PEER_COPY_HOST_F
549+ return 0
550+}
551+
552
553=== modified file 'tests/helpers/test_peer.sh'
554--- tests/helpers/test_peer.sh 2012-01-05 19:35:03 +0000
555+++ tests/helpers/test_peer.sh 2012-01-09 18:47:25 +0000
556@@ -13,6 +13,8 @@
557
558 set -ue
559
560+JUJU_UNIT_NAME="EMPTY"
561+
562 #mock relation-list
563 alias relation-list=mock_relation_list
564 mock_relation_list()
565@@ -20,7 +22,21 @@
566 [ -z $CH_MASTER ] && let CH_MASTER=1
567
568 case $CH_MASTER in
569- 1)
570+ 4)
571+ echo "TEST/3
572+TEST/2
573+TEST/4"
574+ ;;
575+ 3)
576+ echo "TEST/4
577+TEST/3
578+TEST/1"
579+ ;;
580+ 2)
581+ echo "TEST/3
582+TEST/4"
583+ ;;
584+ 1)
585 echo "TEST/2
586 TEST/3
587 TEST/4"
588@@ -30,8 +46,11 @@
589 TEST/3
590 TEST/4"
591 ;;
592- esac
593-
594+ -1)
595+ echo ""
596+ ;;
597+ esac
598+
599 }
600
601 #Save juju-log for debugging
602@@ -41,7 +60,7 @@
603 alias juju-log=mock_juju_log
604 mock_juju_log()
605 {
606- echo "$1" >> $CH_TEMPLOG
607+ echo "$*" >> $CH_TEMPLOG
608 }
609
610 #mock unit-get
611@@ -50,7 +69,7 @@
612 {
613 case $1 in
614 "private-address")
615- echo "127.0.0.1"
616+ echo "localhost"
617 ;;
618 *)
619 echo "UNDEFINED"
620@@ -135,6 +154,9 @@
621 output "Backing up created $HOME/.ssh to $backup_dir/dot-ssh"
622 mv $HOME/.ssh $backup_dir/dot-ssh
623 fi
624+ if [ -e $HOME/ch_test ] ; then
625+ rm -rf $HOME/ch_test
626+ fi
627 }
628 trap cleanup_peer EXIT
629 if [ $debug -gt 0 ] ; then echo "user: $USER, home: $HOME"; fi
630@@ -236,10 +258,53 @@
631 ch_peer_i_am_leader || return 1 && :
632 echo PASS
633
634+start_test "ch_peer_i_am_leader (unordered list 1)..."
635+JUJU_REMOTE_UNIT="TEST/3"
636+JUJU_UNIT_NAME="TEST/2"
637+CH_MASTER=3
638+ch_peer_i_am_leader && return 1 || :
639+echo PASS
640+
641+start_test "ch_peer_i_am_leader (unordered list 2)..."
642+JUJU_UNIT_NAME="TEST/1"
643+CH_MASTER=4
644+ch_peer_i_am_leader || return 1 && :
645+echo PASS
646+
647+start_test "ch_peer_i_am_leader (unordered list 3)..."
648+JUJU_UNIT_NAME="TEST/2"
649+CH_MASTER=3
650+ch_peer_i_am_leader && return 1 || :
651+echo PASS
652+
653+start_test "ch_peer_i_am_leader (unordered list 4)..."
654+JUJU_UNIT_NAME="TEST/3"
655+ch_peer_i_am_leader && return 1 && :
656+echo PASS
657+
658+start_test "ch_peer_i_am_leader (empty list)..."
659+JUJU_REMOTE_UNIT="TEST/3"
660+JUJU_UNIT_NAME="TEST/1"
661+CH_MASTER=-1
662+ch_peer_i_am_leader || return 1 && :
663+echo PASS
664+
665+start_test "ch_peer_i_am_leader (departed leader)..."
666+JUJU_REMOTE_UNIT="TEST/1"
667+JUJU_UNIT_NAME="TEST/4"
668+CH_MASTER=2
669+ch_peer_i_am_leader && return 1 || :
670+JUJU_UNIT_NAME="TEST/2"
671+ch_peer_i_am_leader || return 1 && :
672+echo PASS
673+
674 start_test ch_peer_leader...
675+JUJU_REMOTE_UNIT="TEST/3"
676+JUJU_UNIT_NAME="TEST/1"
677+CH_MASTER=1
678 [ "`ch_peer_leader`" = "TEST/1" ] || return 1
679 [ `ch_peer_leader --id` -eq 1 ] || return 1
680-JUJU_UNIT_NAME="TEST/3"
681+JUJU_UNIT_NAME="TEST/2"
682 [ "`ch_peer_leader`" = "TEST/2" ] || return 1
683 [ `ch_peer_leader --id` -eq 2 ] || return 1
684 echo PASS
685@@ -305,18 +370,102 @@
686 JUJU_UNIT_NAME="TEST/2"
687 JUJU_REMOTE_UNIT="TEST/1"
688 CH_MASTER=0
689- if ch_peer_scp -p $CH_portnum -o "-q" $CH_TEMPDIR/sourcedir/testfile $CH_TEMPDIR/destdir/ ; then break ; fi
690+ if ch_peer_scp -p $CH_portnum -o "-q" "$CH_TEMPDIR/sourcedir/testfile" "$CH_TEMPDIR/destdir/" "$CH_TEMPDIR/sourcedir/testfile1" "$CH_TEMPDIR/destdir/" ; then break ; fi
691 #master relation joined
692 JUJU_UNIT_NAME="TEST/1"
693 JUJU_REMOTE_UNIT="TEST/2"
694 CH_MASTER=1
695- if ch_peer_scp -p $CH_portnum -o "-q" $CH_TEMPDIR/sourcedir/testfile $CH_TEMPDIR/destdir/ ; then break ; fi
696+ if ch_peer_scp -p $CH_portnum -o "-q" "$CH_TEMPDIR/sourcedir/testfile" "$CH_TEMPDIR/destdir/" "$CH_TEMPDIR/sourcedir/testfile1" "$CH_TEMPDIR/destdir/" ; then break ; fi
697 done
698-[ ! -e $CH_TEMPDIR/destdir/testfile ] && output"file not copied" && exit 1
699-CH_t1=`md5sum $CH_TEMPDIR/sourcedir/testfile | cut -d" " -f1`
700-CH_t2=`md5sum $CH_TEMPDIR/destdir/testfile | cut -d" " -f1`
701-[ ! "$CH_t1" = "$CH_t2" ] && output "md5sum differ" && exit 1
702-rm -rf $CH_TEMPDIR/destdir/*
703+[ ! -e $CH_TEMPDIR/destdir/testfile ] && output "file1 not copied" && exit 1
704+[ ! -e $CH_TEMPDIR/destdir/testfile1 ] && output "file2 not copied" && exit 1
705+CH_t1=`md5sum $CH_TEMPDIR/sourcedir/testfile | cut -d" " -f1`
706+CH_t2=`md5sum $CH_TEMPDIR/destdir/testfile | cut -d" " -f1`
707+[ ! "$CH_t1" = "$CH_t2" ] && output "md5sum differ" && exit 1
708+rm -rf $CH_TEMPDIR/destdir/*
709+echo PASS
710+
711+start_test "ch_peer_copy_replay..."
712+CH_scp_hostname=""
713+CH_scp_ssh_key_saved=""
714+CH_scp_ssh_key=""
715+CH_scp_copy_done=""
716+#We are not in a relation, we are on master
717+JUJU_UNIT_NAME="TEST/1"
718+JUJU_REMOTE_UNIT=""
719+CH_MASTER=-1
720+if ! ch_peer_copy_replay ; then
721+ output "should not have returned not copied (1)"
722+ exit 1
723+fi
724+#We are not in a relation, we are on slave
725+JUJU_UNIT_NAME="TEST/2"
726+JUJU_REMOTE_UNIT=""
727+CH_MASTER=-1
728+if ch_peer_copy_replay ; then
729+ output "should not have returned copied (0)"
730+ exit 1
731+fi
732+[ ! -e $CH_TEMPDIR/destdir/testfile ] && output "file not copied" && exit 1
733+CH_t1=`md5sum $CH_TEMPDIR/sourcedir/testfile | cut -d" " -f1`
734+CH_t2=`md5sum $CH_TEMPDIR/destdir/testfile | cut -d" " -f1`
735+[ ! "$CH_t1" = "$CH_t2" ] && output "md5sum differ" && exit 1
736+[ ! -e $CH_TEMPDIR/destdir/ ] && output "dir not copied" && exit 1
737+[ ! -e $CH_TEMPDIR/destdir/testfile0 ] && output "file1 not copied" && exit 1
738+[ ! -e $CH_TEMPDIR/destdir/testfile1 ] && output "file2 not copied" && exit 1
739+CH_t1=`md5sum $CH_TEMPDIR/sourcedir/testfile0 | cut -d" " -f1`
740+CH_t2=`md5sum $CH_TEMPDIR/destdir/testfile0 | cut -d" " -f1`
741+[ ! "$CH_t1" = "$CH_t2" ] && output "md5sum differ" && exit 1
742+rm -rf $CH_TEMPDIR/destdir/*
743+echo PASS
744+
745+start_test "ch_peer_rsync (out of relation)..."
746+CH_scp_hostname=""
747+CH_scp_ssh_key_saved=""
748+CH_scp_ssh_key=""
749+CH_scp_copy_done=""
750+#We are not in a relation, we are on master
751+JUJU_UNIT_NAME="TEST/1"
752+JUJU_REMOTE_UNIT=""
753+CH_MASTER=-1
754+ch_peer_rsync -p $CH_portnum -o "-azq" "$CH_TEMPDIR/sourcedir/*" "$CH_TEMPDIR/destdir/" && chres=0 || chres=$?
755+if [ $chres -ne 101 ] ; then
756+ output "should not have returned not copied (received $chres, 101 expected)"
757+ exit 1
758+fi
759+#We are not in a relation, we are on slave
760+JUJU_UNIT_NAME="TEST/2"
761+JUJU_REMOTE_UNIT=""
762+CH_MASTER=-1
763+ch_peer_rsync -p $CH_portnum -o "-azq" "$CH_TEMPDIR/sourcedir/*" "$CH_TEMPDIR/destdir/" && chres=0 || chres=$?
764+if [ $chres -ne 100 ] ; then
765+ output "should not have returned copied (received $chres, 100 expected)"
766+ exit 1
767+fi
768+[ ! -e $CH_TEMPDIR/destdir/ ] && output "dir not copied" && exit 1
769+[ ! -e $CH_TEMPDIR/destdir/testfile0 ] && output "file1 not copied" && exit 1
770+[ ! -e $CH_TEMPDIR/destdir/testfile1 ] && output "file2 not copied" && exit 1
771+CH_t1=`md5sum $CH_TEMPDIR/sourcedir/testfile0 | cut -d" " -f1`
772+CH_t2=`md5sum $CH_TEMPDIR/destdir/testfile0 | cut -d" " -f1`
773+[ ! "$CH_t1" = "$CH_t2" ] && output "md5sum differ" && exit 1
774+rm -rf $CH_TEMPDIR/destdir/*
775+#restore authorized_keys & known_hosts
776+echo PASS
777+
778+start_test "ch_peer_copy_cleanup..."
779+# as a leader
780+JUJU_UNIT_NAME="TEST/1"
781+JUJU_REMOTE_UNIT="TEST/2"
782+CH_MASTER=-1
783+ch_peer_copy_cleanup "$JUJU_REMOTE_UNIT"
784+unitname=`echo $JUJU_UNIT_NAME | sed 's/\//-/g'`
785+[ `grep -F "$JUJU_REMOTE_UNIT" $HOME/ch_test/$unitname` ] && output "not cleaned up" && exit 1
786+# as a slave
787+JUJU_UNIT_NAME="TEST/2"
788+JUJU_REMOTE_UNIT="TEST/1"
789+CH_MASTER=-1
790+ch_peer_copy_cleanup "$JUJU_REMOTE_UNIT"
791+#nothing to check here other than if we did not choke on cleaning up something that does not exist
792 echo PASS
793
794 trap - EXIT

Subscribers

People subscribed via source and target branches