root / bin / zfs-replica @ 67
Historique | Voir | Annoter | Télécharger (11,13 ko)
1 |
#!/bin/bash |
---|---|
2 |
# $Id: zfs-replica 67 2016-04-18 13:58:46Z ltaulell $ |
3 |
# Copyright (C) 2013 Kevin Reverchon, Loïs Taulelle |
4 |
# This file/program is part of gZFS free software |
5 |
# See COPYING file for details |
6 |
# |
7 |
|
8 |
#--- Define variables ---# |
9 |
DIR_CONF_REPLICA="/opt/gZFS/replicas/" |
10 |
getConfigSnapshotTool="/sbin/get-conf-snapshot" |
11 |
zfsSnapshot="/sbin/zfs-snapshot" |
12 |
FILE_NAME=$1 |
13 |
TEMP_FILE_NAME="$1-tmp" |
14 |
>$TEMP_FILE_NAME |
15 |
BINZFS="/sbin/zfs" |
16 |
BINZPOOL="/sbin/zpool" |
17 |
BINMBUFFER="mbuffer -4 -v 0 -q -s 128k -m 1G" |
18 |
LOCALHOST=$(hostname -s) |
19 |
|
20 |
LOGFILEROTATE=21 |
21 |
LOGDIR="/var/log/zfs-replica" |
22 |
|
23 |
if [ "$2" == "--cronlog" ]; |
24 |
then |
25 |
LOG=true |
26 |
if [ ! -d $LOGDIR ]; |
27 |
then |
28 |
mkdir -p $LOGDIR |
29 |
fi |
30 |
else |
31 |
LOG=false |
32 |
fi |
33 |
|
34 |
#******************************** |
35 |
#* function ok_exit |
36 |
#******************************* |
37 |
function ok_exit { |
38 |
if $LOG; then |
39 |
echo $1 1>&2 |
40 |
# restauration de stderr et stdout, fermeture des fd temporaires |
41 |
exec 2>&7 7>&- |
42 |
exec 1>&6 6>&- |
43 |
fi |
44 |
exit 0 |
45 |
} |
46 |
|
47 |
#******************************** |
48 |
#* function err_exit |
49 |
#******************************* |
50 |
function err_exit { |
51 |
if $LOG; then |
52 |
echo $1 1>&2 |
53 |
# restauration de stderr et stdout, fermeture des fd temporaires |
54 |
exec 2>&7 7>&- |
55 |
exec 1>&6 6>&- |
56 |
fi |
57 |
cat $LOGFILE |
58 |
exit 1 |
59 |
} |
60 |
|
61 |
#******************************** |
62 |
#* function initenv |
63 |
#******************************* |
64 |
function initenv { |
65 |
if [[ -z $FILE_NAME ]] |
66 |
then |
67 |
echo "/!\\ Replica Configuration file missing /!\\" 1>&2 |
68 |
exit 1 |
69 |
fi |
70 |
|
71 |
if [ ! -s $FILE_NAME ] |
72 |
then |
73 |
echo "Replica Configuration file not found" |
74 |
exit 0 |
75 |
fi |
76 |
lastsnapshotReplicated=$(cat $FILE_NAME|grep lastsnapshotreplicated|cut -d "=" -f2) |
77 |
server=$(cat $FILE_NAME|grep server|cut -d "=" -f2) |
78 |
nbreplica=$(cat $FILE_NAME|grep nbreplica|cut -d "=" -f2) |
79 |
namereplica=$(cat $FILE_NAME|grep namereplica|cut -d "=" -f2) |
80 |
namevolfs=$(cat $FILE_NAME|grep "name="|cut -d "=" -f2) |
81 |
|
82 |
if $LOG; |
83 |
then |
84 |
LOGFILE="$LOGDIR/${namevolfs//\//-}.log" |
85 |
|
86 |
if [ -f $LOGFILE ]; |
87 |
then |
88 |
savelog -t -c $LOGFILEROTATE -q -n $LOGFILE |
89 |
fi |
90 |
|
91 |
# sauvegarde de stdout et stderr dans des fd (file descriptor) temporaires |
92 |
#+redirection de stdout vers $TMPFILE |
93 |
#+redirection de stderr vers stdout |
94 |
#+ = ">> $TMPFILE 2>&1" |
95 |
exec 6>&1 7>&2 |
96 |
exec 1>$LOGFILE |
97 |
exec 2>&1 |
98 |
fi |
99 |
|
100 |
if [[ -z $namereplica ]] || [[ -z $nbreplica ]] || [[ -z $namevolfs ]] |
101 |
then |
102 |
err_exit "Incoherence data in $FILE_NAME" |
103 |
fi |
104 |
|
105 |
echo "$getConfigSnapshotTool $namevolfs" |
106 |
getlistSnapshot=$($getConfigSnapshotTool $namevolfs) |
107 |
if [[ "$getlistSnapshot" == "" ]] |
108 |
then |
109 |
err_exit "Please, enable a snapshot configuration for $namevolfs" |
110 |
fi |
111 |
} |
112 |
|
113 |
#**************************************** |
114 |
#* function check server ssh connection |
115 |
#*************************************** |
116 |
function checkServerConnection { |
117 |
|
118 |
ssh -o BatchMode=yes root@$server date |
119 |
|
120 |
if [ "$?" != "0" ] |
121 |
then |
122 |
err_exit "SSH Connection server $server failed, please check the private/public key" |
123 |
fi |
124 |
|
125 |
} |
126 |
|
127 |
function computePort { |
128 |
# add a number, based on replica name, to mbuffer base port. |
129 |
# This try to avoid problems, on multiple replicas cases, such as reception of |
130 |
# different replicas on same mbuffer port: yeah, epic fail! |
131 |
BasePORT="1030" |
132 |
#for i in $(echo $snapshot2replicate| od -An -t u1); do j=$(($j+$i)); echo $j; done |
133 |
SumChar=0 |
134 |
BaseChars=$(echo $snapshot2replicate | od -An -t u1) |
135 |
for i in $BaseChars |
136 |
do |
137 |
SumChar=$(($SumChar+$i)) |
138 |
done |
139 |
PORT=$(($BasePORT+$SumChar)) |
140 |
} |
141 |
|
142 |
|
143 |
function checkCoherence { |
144 |
ssh -o BatchMode=yes root@$server $BINZFS list $namereplica |
145 |
if [ "$?" != "0" ] |
146 |
then |
147 |
return false |
148 |
fi |
149 |
|
150 |
} |
151 |
|
152 |
function del_old_snapshot { |
153 |
#*** ETAPE SUPPRESSION DES SNAPSHOTS OBSELETES ***# |
154 |
if [[ "$server" == "" ]] |
155 |
then |
156 |
echo "" |
157 |
CPT_SNAP=$($BINZFS list -t snapshot -r $namereplica |cut -d" " -f1 |grep -i $namereplica\@ |wc -l) |
158 |
echo "*** Number of snapshots for $namereplica is : $CPT_SNAP" |
159 |
$BINZFS list -t snapshot -r $namereplica |
160 |
|
161 |
if [ $CPT_SNAP -gt $nbreplica ] |
162 |
then |
163 |
echo "*** Detection of the oldest snapshot" |
164 |
for ID_SNAP_OLDER in $($BINZFS list -t snapshot -r $namereplica |cut -d" " -f1 |grep -i $namereplica\@) |
165 |
do |
166 |
echo "*** The oldest snapshot is : $ID_SNAP_OLDER" |
167 |
break |
168 |
done |
169 |
$BINZFS destroy $ID_SNAP_OLDER |
170 |
if [ $? -eq 0 ] |
171 |
then |
172 |
echo "*** Remove the snapshot $ID_SNAP_OLDER [OK]" |
173 |
else |
174 |
echo "/!\\ Remove the snapshot $ID_SNAP_OLDER [ERROR]." |
175 |
fi |
176 |
fi |
177 |
|
178 |
else |
179 |
echo "" |
180 |
CPT_SNAP=$(ssh -o BatchMode=yes root@$server $BINZFS list -t snapshot -r $namereplica |cut -d" " -f1 |grep -i $namereplica\@ |wc -l) |
181 |
echo "*** Number of snapshots for $namereplica is : $CPT_SNAP" |
182 |
ssh -o BatchMode=yes root@$server $BINZFS list -t snapshot -r $namereplica |
183 |
|
184 |
if [ $CPT_SNAP -gt $nbreplica ] |
185 |
then |
186 |
echo "*** Detection of the oldest snapshot" |
187 |
for ID_SNAP_OLDER in $(ssh -o BatchMode=yes root@$server $BINZFS list -t snapshot -r $namereplica |cut -d" " -f1 |grep -i $namereplica\@) |
188 |
do |
189 |
echo "*** The oldest snapshot is : $ID_SNAP_OLDER" |
190 |
break |
191 |
done |
192 |
ssh -o BatchMode=yes root@$server $BINZFS destroy $ID_SNAP_OLDER |
193 |
if [ $? -eq 0 ] |
194 |
then |
195 |
echo "*** Remove the snapshot $ID_SNAP_OLDER [OK]" |
196 |
else |
197 |
echo "/!\\ Remove the snapshot $ID_SNAP_OLDER [ERROR]." |
198 |
fi |
199 |
fi |
200 |
|
201 |
fi |
202 |
#*** FIN ETAPE SUPPRESSION DES SNAPSHOTS OBSELETES ***# |
203 |
} |
204 |
|
205 |
|
206 |
#************************************* |
207 |
#* function FULL REPLICATION |
208 |
#************************************* |
209 |
function fullreplication { |
210 |
|
211 |
parentdataset=$(awk '{ |
212 |
n = split($0, t, "/") |
213 |
for (i = 0; ++i <= n-1;) |
214 |
if (i == 1) |
215 |
printf t[i] |
216 |
else |
217 |
printf "/"t[i] |
218 |
}' <<< $(echo $namereplica)) |
219 |
|
220 |
if [[ "$server" == "" ]] |
221 |
then |
222 |
|
223 |
$BINZFS list $parentdataset |
224 |
if [[ "?" != "0" ]] |
225 |
then |
226 |
$BINZFS create -p $parentdataset |
227 |
fi |
228 |
|
229 |
$BINZFS send $snapshot2replicate | $BINZFS recv $namereplica |
230 |
if [[ "$?" == "0" ]] |
231 |
then |
232 |
while read line |
233 |
do |
234 |
$(echo $line|sed -e "s:lastsnapshotreplicated=.*$:lastsnapshotreplicated=$snapshot2replicate:g" >>$TEMP_FILE_NAME) |
235 |
done <<< "$(cat $FILE_NAME)" |
236 |
/bin/rm $FILE_NAME |
237 |
/bin/mv $TEMP_FILE_NAME $FILE_NAME |
238 |
del_old_snapshot |
239 |
ok_exit |
240 |
fi |
241 |
|
242 |
else |
243 |
checkServerConnection |
244 |
if [[ "$snapshot2replicate" != "" ]] |
245 |
then |
246 |
ssh -o BatchMode=yes root@$server $BINZFS list $parentdataset |
247 |
if [[ "?" != "0" ]] |
248 |
then |
249 |
ssh -o BatchMode=yes root@$server $BINZFS create -p $parentdataset |
250 |
fi |
251 |
|
252 |
# $BINZFS send $snapshot2replicate |ssh -o BatchMode=yes root@$server $BINZFS recv $namereplica |
253 |
computePort |
254 |
ssh -o BatchMode=yes root@$server "$BINMBUFFER -I $LOCALHOST:$PORT | $BINZFS recv $namereplica " & |
255 |
sleep 5s # allow server to be ready |
256 |
$BINZFS send $snapshot2replicate | $BINMBUFFER -O $server:$PORT |
257 |
if [[ "$?" == "0" ]] |
258 |
then |
259 |
while read line |
260 |
do |
261 |
$(echo $line|sed -e "s:lastsnapshotreplicated=.*$:lastsnapshotreplicated=$snapshot2replicate:g" >>$TEMP_FILE_NAME) |
262 |
done <<< "$(cat $FILE_NAME)" |
263 |
/bin/rm $FILE_NAME |
264 |
/bin/mv $TEMP_FILE_NAME $FILE_NAME |
265 |
del_old_snapshot |
266 |
ok_exit |
267 |
fi |
268 |
fi |
269 |
fi |
270 |
|
271 |
} |
272 |
|
273 |
|
274 |
|
275 |
function incremental_replication { |
276 |
|
277 |
echo "Start incremental replication for : $snasphot2replicate" |
278 |
if [[ "$server" == "" ]] |
279 |
then |
280 |
$BINZFS send -i $lastsnapshotReplicated $namevolfs@$snasphot2replicate | $BINZFS recv $namereplica |
281 |
snapshot2replicate="$namevolfs@$snasphot2replicate" |
282 |
if [[ "$?" == "0" ]] |
283 |
then |
284 |
while read line |
285 |
do |
286 |
echo $line|sed -e "s:lastsnapshotreplicated=.*$:lastsnapshotreplicated=$snapshot2replicate:g" >>$TEMP_FILE_NAME |
287 |
done <<< "$(cat $FILE_NAME)" |
288 |
/bin/rm $FILE_NAME |
289 |
/bin/mv $TEMP_FILE_NAME $FILE_NAME |
290 |
del_old_snapshot |
291 |
ok_exit |
292 |
fi |
293 |
else |
294 |
checkServerConnection |
295 |
if [ "$snasphot2replicate" == "" ] |
296 |
then |
297 |
err_exit |
298 |
else |
299 |
#$BINZFS send -i $lastsnapshotReplicated $namevolfs@$snasphot2replicate | ssh -o BatchMode=yes root@$server $BINZFS recv $namereplica |
300 |
computePort |
301 |
ssh -o BatchMode=yes root@$server "$BINMBUFFER -I $LOCALHOST:$PORT | $BINZFS recv $namereplica " & |
302 |
sleep 5s # allow server to be ready |
303 |
$BINZFS send -i $lastsnapshotReplicated $namevolfs@$snasphot2replicate | $BINMBUFFER -O $server:$PORT |
304 |
snapshot2replicate="$namevolfs@$snasphot2replicate" |
305 |
if [[ "$?" == "0" ]] |
306 |
then |
307 |
while read line |
308 |
do |
309 |
$(echo $line|sed -e "s:lastsnapshotreplicated=.*$:lastsnapshotreplicated=$snapshot2replicate:g" >>$TEMP_FILE_NAME) |
310 |
done <<< "$(cat $FILE_NAME)" |
311 |
/bin/rm $FILE_NAME |
312 |
/bin/mv $TEMP_FILE_NAME $FILE_NAME |
313 |
del_old_snapshot |
314 |
ok_exit |
315 |
fi |
316 |
fi |
317 |
fi |
318 |
|
319 |
} |
320 |
|
321 |
|
322 |
#**************************************** |
323 |
#* NO INTERACTIVE MODE |
324 |
#**************************************** |
325 |
function nointeractive { |
326 |
|
327 |
#--- check and init env ---# |
328 |
initenv |
329 |
|
330 |
fileconf=$($getConfigSnapshotTool $namevolfs|grep fileconf|cut -d "=" -f2) |
331 |
NBsnapshot=$($BINZFS list -H -r -t snapshot $namevolfs|wc -l) |
332 |
|
333 |
if [[ $NBsnapshot -eq 0 ]] |
334 |
then |
335 |
echo "no snapshot, start snapshoting ..." |
336 |
$zfsSnapshot $fileconf |
337 |
fi |
338 |
|
339 |
valchk=checkCoherence |
340 |
if [[ "$valchk" == "false" ]] && [[ "$lastsnapshotReplicated" != "" ]] |
341 |
then |
342 |
echo "Replication by incremental snapshot is not possible : checkcoherence return false " |
343 |
echo "Start FULL Replication ..." |
344 |
while read line |
345 |
do |
346 |
snapshot2replicate=$(echo $line |echo $line |sed -e "s/ \+/ /g"|cut -d " " -f1) |
347 |
done <<< "$($BINZFS list -H -r -t snapshot $namevolfs)" |
348 |
fullreplication |
349 |
fi |
350 |
|
351 |
|
352 |
#--- FULL REPLICATION ---# |
353 |
if [[ $NBsnasphot -eq 1 ]] || [[ "$lastsnapshotReplicated" == "" ]] |
354 |
then |
355 |
echo "Replication by incremental snapshot is not possible" |
356 |
echo "Start FULL Replication ..." |
357 |
while read line |
358 |
do |
359 |
snapshot2replicate=$(echo $line |echo $line |sed -e "s/ \+/ /g"|cut -d " " -f1) |
360 |
done <<< "$($BINZFS list -H -r -t snapshot $namevolfs)" |
361 |
fullreplication |
362 |
fi |
363 |
|
364 |
#-- INCREMENTAL REPLICATION ---# |
365 |
if [[ $NBsnapshot -gt 1 ]] |
366 |
then |
367 |
cpt=1 |
368 |
while read line |
369 |
do |
370 |
|
371 |
if [[ $cpt -eq 1 ]] |
372 |
then |
373 |
snasphot2replicate=$(echo $line |sed -e "s/ \+/ /g"|cut -d " " -f1|cut -d "@" -f2) |
374 |
echo $lastsnasphot |
375 |
echo $snasphot2replicate |
376 |
break |
377 |
fi |
378 |
cpt=$cpt+1 |
379 |
done <<< "$($BINZFS list -H -r -t snapshot $namevolfs|tac)" |
380 |
lastsnapshot=$(echo $lastsnapshotReplicated |sed -e "s/ \+/ /g"|cut -d " " -f1|cut -d "@" -f2) |
381 |
|
382 |
if [ "$snasphot2replicate" == "$lastsnapshot" ] |
383 |
then |
384 |
err_exit "Nothing to replicate" |
385 |
|
386 |
fi |
387 |
if [ "$server" == "" ] |
388 |
then |
389 |
check_lastsnapshotReplica=$($BINZFS list -H -r -t snapshot $namereplica |grep $lastsnapshot|wc -l) |
390 |
check_currentsnapshotReplica=$($BINZFS list -H -r -t snapshot $namereplica |grep $snasphot2replicate=|wc -l) |
391 |
else |
392 |
check_lastsnapshotReplica=$(ssh -o BatchMode=yes root@$server $BINZFS list -H -r -t snapshot $namereplica |grep $lastsnapshot|wc -l) |
393 |
check_currentsnapshotReplica=$(ssh -o BatchMode=yes root@$server $BINZFS list -H -r -t snapshot $namereplica |grep $snasphot2replicate=|wc -l) |
394 |
fi |
395 |
if [[ $check_lastsnapshotReplica -eq 0 ]] |
396 |
then |
397 |
err_exit "Incoherence, incremental replication failed : $lastsnapshotReplicated is missing" |
398 |
fi |
399 |
|
400 |
if [[ $check_currentsnapshotReplica -eq 1 ]] |
401 |
then |
402 |
err_exit "No replica to do, $lastSnapshot already exists" |
403 |
fi |
404 |
fi |
405 |
echo $snasphot2replicate |
406 |
incremental_replication |
407 |
} |
408 |
|
409 |
nointeractive |
410 |
|
411 |
# restauration de stderr et stdout, fermeture des fd temporaires |
412 |
exec 2>&7 7>&- |
413 |
exec 1>&6 6>&- |
414 |
|