Statistiques
| Révision :

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