Changeset 5116ce8


Ignore:
Timestamp:
04/02/15 15:06:00 (5 months ago)
Author:
Kris Moore <kris@…>
Branches:
master, enter/10, releng/10.1.2, releng/10.2, stable/10
Children:
327702a
Parents:
bb204f2
Message:

Large update to Life-Preserver replication engine,

Now we will handle the creation of clones on the remote, and add
a new method to save dataset properties via user-prop on the remote
side. This will keep remote side from trying to act upon system props

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src-sh/lpreserver/backend/functions.sh

    rd5a61ec r5116ce8  
    766766} 
    767767 
    768 # Before we replicate, we need to traverse $1 dataset and save 
    769 # our dataset mountpoint properties. Then after replication we 
    770 # can unset the mountpoint= property, so that the replication 
    771 # server won't try to mount all the datasets at reboot 
    772 save_mount_props() { 
    773   for dSet in `zfs list -r -H ${1} | awk '{print $1}'` 
     768# After replication of a dataset, we need to save local properties of that set 
     769save_remote_props() { 
     770  local dset="$1" 
     771 
     772  # Get list of local props for this dataset 
     773  zfs get -H -s local -o property,value all ${dset} | tr '\t' ' ' > /tmp/.dProps.$$ 
     774 
     775  # Now set these as user-props on the remote side 
     776  while read propline 
    774777  do 
    775     mPoint=`zfs list -H -o mountpoint ${dSet}` 
    776     if [ -z "$mPoint" -o "$mPoint" = "-" ] ; then continue; fi 
    777     zfs set lpreserver:mount="$mPoint" ${dSet} 
     778    pname="`echo $propline | cut -d ' ' -f 1`" 
     779    pval="`echo $propline | cut -d ' ' -f 2-`" 
     780    if [ -z "$pname" -o "$pval" = "-" ] ; then continue; fi 
     781    rdset="" 
     782    if [ "$dset" != "$LDATA" ] ; then 
     783      # Strip off the zpool/top level name 
     784      rdset=`echo $dset | sed "s|^${LDATA}||g"` 
     785    fi 
     786 
     787    # Set the property now 
     788    ${CMDPREFIX} zfs set lifepreserver-prop:${pname}="${pval}" ${REMOTEDSET}/${hName}${rdset} 
    778789    if [ $? -ne 0 ] ; then 
    779       echo_log "WARNING: Failed to set lpreserver:mount=$mPoint property on ${dSet}" 
    780       queue_msg "`date`: Failed to set lpreserver:mount=$mPoint property on ${dSet}\n" 
    781     fi 
    782   done 
    783 } 
    784  
    785 # After a successful replication, we can now unset the mountpoint 
    786 # properties, so that remote system doesn't try to mount backup 
    787 # datasets after a power loss / reboot 
    788 unset_mount_props() { 
    789   build_dset_list "$1" "rep" 
    790   for dSet in $DSETS 
    791   do 
    792     mPoint=`zfs list -H -o mountpoint ${dSet}` 
    793     # It no mountpoint set on this dataset, we can skip 
    794     if [ -z "$mPoint" -o "$mPoint" = "-" ] ; then continue; fi 
    795  
    796     if [ "$dSet" = "$1" ] ; then 
    797       rdSet="${REPRDATA}/${hName}" 
    798     else 
    799       cleanDSet=`echo ${dSet} | sed "s|^${1}/||g"` 
    800       rdSet="${REPRDATA}/${hName}/${cleanDSet}" 
    801     fi 
    802     ssh -p ${REPPORT} ${REPUSER}@${REPHOST} "zfs set mountpoint=none ${rdSet}" 
    803     if [ $? -ne 0 ] ; then 
    804       echo_log "WARNING: Failed unsetting mountpoint property for: ${rdSet}" 
    805       queue_msg "`date`: Failed unsetting mountpoint property for: ${rdSet}\n" 
    806     fi 
    807   done 
     790      echo "WARNING: Failed to set lifepreserver-prop:$pname=$pval property on ${dset}" 
     791      echo_log "WARNING: Failed to set lifepreserver-prop:$pname=$pval property on ${dset}" 
     792      queue_msg "`date`: Failed to set lifepreserver-prop:$pname=$pval property on ${dset}\n" 
     793    fi 
     794  done < /tmp/.dProps.$$ 
     795  rm /tmp/.dProps.$$ 2>/dev/null 
    808796} 
    809797 
     
    898886  hName=`hostname` 
    899887 
    900   save_mount_props "${DATASET}" 
     888  #save_mount_props "${DATASET}" 
    901889 
    902890  # Set the remote dataset we are targeting 
     
    944932  # Grab a list of snapshots from remote 
    945933  _rSnapList="/tmp/.remoteZSnap.$$" 
    946   ${CMDPREFIX} zfs list -r -t snap -o name ${REMOTEDSET}/${hName} >${_rSnapList} 2>/dev/null 
     934  ${CMDPREFIX} zfs list -r -t snap -o name ${REMOTEDSET}/${hName} 2>/dev/null | sed "s|^${REMOTEDSET}/${hName}||g" >${_rSnapList} 
    947935 
    948936  # Get list of datasets 
     
    951939  # Get list of remote datasets 
    952940  _rDsetList="/tmp/.remoteDSets.$$" 
    953   ${CMDPREFIX} zfs list -H -r -o name ${REMOTEDSET}/${hName} 2>/dev/null | sed "s|^${REMOTEDSET}/${hName}||g" >${_rDsetList} 
     941  ${CMDPREFIX} zfs list -H -r -o name,origin ${REMOTEDSET}/${hName} 2>/dev/null | sed "s|^${REMOTEDSET}/${hName}||g" >${_rDsetList} 
     942  sync 
    954943 
    955944  # Remove any remote datasets which no longer exist for replication here 
    956   while read rdset 
     945  while read rdline 
    957946  do 
    958     if [ -z "$rdset" ] ; then continue; fi 
     947    if [ -z "${rdline}" ] ; then continue; fi 
    959948    noprune=0 
     949    rdset="`echo ${rdline} | tr -s '\t' ' ' | cut -d ' ' -f 1`" 
    960950    for dset in ${DSETS} 
    961951    do 
     952      if [ "$dset" = "$LDATA" ] ; then noprune=1 ; continue ; fi 
    962953      dcmp="/`echo $dset | cut -d '/' -f 2-`" 
    963       if [ "$rdset" = "$dcmp" ] ; then noprune=1; break; fi 
     954      if [ "$rdset" = "$dcmp" ] ; then noprune=1; continue; fi 
    964955    done 
    965956    if [ $noprune = 0 ] ; then 
     
    971962    fi 
    972963  done < ${_rDsetList} 
    973   rm ${_rDsetList} 2>/dev/null 
    974964 
    975965  # Now go through all datasets and do the replication 
    976966  for dset in ${DSETS} 
    977967  do 
     968 
     969    # If we are on the top level dataset, remove the name from what we receive 
     970    rdset="" 
     971    unset rdsetorigin 
     972    unset ldsetorigin 
     973 
     974    # If on a sub-dataset, check the origin property for clones 
     975    removedRemote=0 
     976    if [ "$dset" != "$LDATA" ] ; then 
     977      # Strip off the zpool/top level name 
     978      rdset=`echo $dset | sed "s|^${LDATA}||g"` 
     979 
     980      # Check if we have a remote dataset origin 
     981      rdsetorigin=`cat ${_rDsetList} | tr -s '\t' ' ' | grep "^${rdset} " | cut -d ' ' -f 2` 
     982      ldsetorigin=`zfs list -H -o origin $dset` 
     983 
     984      if [ -n "$rdsetorigin" ] ; then 
     985        # Lets get the clone / origin properties 
     986        cmp1=`echo $rdsetorigin | sed "s|^${REMOTEDSET}/${hName}||g"` 
     987        cmp2=`echo $ldsetorigin | sed "s|^${LDATA}||g"` 
     988        if [ -n "$rdsetorigin" -a "$cmp1" != "$cmp2" ] ; then 
     989           echo "Local dataset does NOT equal remote: $dset > $cmp1 != $cmp2" 
     990           # If the local dataset is now the parent, we can try promoting the remote dataset 
     991           if [ "$ldsetorigin" = "-" ] ; then 
     992              echo "Need to promote clone!" 
     993           else 
     994              removedRemote=1 
     995              queue_msg "`date`: Removing ${REMOTEDSET}/${hName}${rdset} - Incorrect origin" 
     996              ${CMDPREFIX} zfs destroy -r ${REMOTEDSET}/${hName}${rdset} 
     997           fi 
     998        fi 
     999      else 
     1000        if [ "$ldsetorigin" = "-" ] ; then unset ldsetorigin ; fi 
     1001      fi # End of if rdsetorigin exists 
     1002    fi 
     1003 
    9781004    # Was this particular dataset already sent? 
    9791005    lastSENDPART=`zfs get -d 1 lpreserver-part:${REPHOST} ${dset} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1` 
    980     if [ -n "$lastSENDPART" ] ; then 
     1006    if [ -n "$lastSENDPART" -a "$removedRemote" = "0" ] ; then 
    9811007       # This one is already replicated, lets skip it 
    9821008       if [ "${lastSENDPART}" = "${lastSNAP}" ] ; then 
     
    9861012       fi 
    9871013    fi 
    988  
    989     # If we are on the top level dataset, remove the name from what we receive 
    990     if [ "$dset" = "$LDATA" ] ; then 
    991       rdset="" 
    992     else 
    993       # Strip off the zpool/top level name 
    994       rdset="/`echo $dset | cut -d '/' -f 2-`" 
     1014    if [ "$removedRemote" = "1" ] ; then 
     1015      if [ -n "$lastSENDPART" ] ; then 
     1016        zfs set lpreserver-part:${REPHOST}=' ' ${dset}@$lastSENDPART 
     1017      fi 
     1018      lastSENDPART="" 
    9951019    fi 
    9961020 
    9971021    # Check the remote, if the snapshot already exists, we can skip this one 
    998     grep -q "${REMOTEDSET}/${hName}${rdset}@${lastSNAP}" ${_rSnapList} 
     1022    grep -q "^${rdset}@${lastSNAP}" ${_rSnapList} 
    9991023    if [ $? -eq 0 ] ; then 
    10001024      queue_msg "`date`: Skipping already replicated: ${dset}@${lastSNAP}" 
     
    10131037    fi 
    10141038 
     1039    unset firstSNAP 
     1040    unset zFLAGSFIRST 
     1041    zFLAGSRCV="-u -v -F ${REMOTEDSET}/${hName}${rdset}" 
    10151042    # Starting replication, first lets check if we can do an incremental send 
    10161043    if [ -n "$lastSENDPART" ] ; then 
    1017        zFLAGS="-v -D -I ${lastSENDPART} ${dset}@${lastSNAP}" 
     1044       zFLAGS="-v -I ${lastSENDPART} ${dset}@${lastSNAP}" 
    10181045    else 
    1019        zFLAGS="-v -D -p ${dset}@${lastSNAP}" 
    1020        ${CMDPREFIX} zfs create -o mountpoint=none ${REMOTEDSET}/${hName}${rdset} >${CMDLOG} 2>${CMDLOG} 
    1021     fi 
    1022  
    1023     zSEND="zfs send $zFLAGS" 
    1024     zRCV="${CMDPREFIX} zfs receive -u -v -F ${REMOTEDSET}/${hName}${rdset}" 
    1025  
    1026     queue_msg "Using ZFS send command:\n$zSEND | $zRCV\n\n" 
    1027  
    1028     # Start up our process 
    1029     $zSEND 2>${REPLOGSEND} | $zRCV >${REPLOGRECV} 2>${REPLOGRECV} 
     1046       # If the local dataset is the parent, we can create 
     1047       if [ -z "$ldsetorigin" ] ; then 
     1048         firstSNAP="`zfs list -H -d 1 -t snapshot -o name ${dset} | head -n 1 | cut -d '@' -f 2`" 
     1049         zFLAGS="-v -I ${firstSNAP} ${dset}@${lastSNAP}" 
     1050         zFLAGSFIRST="-v ${dset}@${firstSNAP}" 
     1051         echo "${CMDPREFIX} zfs create -o mountpoint=none -o compression=lz4 ${REMOTEDSET}/${hName}${rdset}" 
     1052         ${CMDPREFIX} zfs create -o mountpoint=none -o compression=lz4 ${REMOTEDSET}/${hName}${rdset} >${CMDLOG} 2>${CMDLOG} 
     1053         if [ $? -ne 0 ] ; then 
     1054           echo "Failed creating remote dataset!" 
     1055           cat ${CMDLOG} 
     1056           zStatus=1 
     1057           break 
     1058         fi 
     1059       else 
     1060         # If the local dataset is cloned, we can clone the remote dataset as well (Was previously replicated) 
     1061         roriginsnap=`echo $ldsetorigin | sed "s|^${LDATA}||g"` 
     1062         zFLAGS="-v -I ${ldsetorigin} ${dset}@${lastSNAP}" 
     1063       fi 
     1064    fi 
     1065 
     1066    # If we are doing the initial replication, start with first snap 
     1067    if [ -n "$firstSNAP" ] ; then 
     1068      do_zfs_send_now "$zFLAGSFIRST" "$zFLAGSRCV" "$firstSNAP" 
     1069      zStatus=$? 
     1070      if [ $zStatus -ne 0 ] ; then break ; fi 
     1071 
     1072      # If the firstSNAP is the same as the lastSNAP then we can skip incremental 
     1073      if [ "$firstSNAP" = "$lastSNAP" ] ; then 
     1074        # Now that replication of this dataset is done, save properties on remote 
     1075        save_remote_props "${dset}" 
     1076        zStatus=$? 
     1077        if [ $zStatus -ne 0 ] ; then break ; fi 
     1078        continue 
     1079      fi 
     1080    fi 
     1081 
     1082    # Do the incremental send/recv now 
     1083    do_zfs_send_now "$zFLAGS" "$zFLAGSRCV" "$lastSNAP" 
    10301084    zStatus=$? 
    1031  
    1032     queue_msg "ZFS SEND LOG:\n--------------\n" "${REPLOGSEND}" 
    1033     queue_msg "ZFS RCV LOG:\n--------------\n" "${REPLOGRECV}" 
    1034  
    10351085    if [ $zStatus -ne 0 ] ; then break ; fi 
    10361086 
    1037     if [ -n "$lastSENDPART" ] ; then 
    1038       zfs set lpreserver-part:${REPHOST}=' ' ${dset}@$lastSENDPART 
    1039     fi 
    1040     zfs set lpreserver-part:${REPHOST}=LATEST ${dset}@$lastSNAP 
     1087    # Now that replication of this dataset is done, save properties on remote 
     1088    save_remote_props "${dset}" 
     1089    zStatus=$? 
     1090    if [ $zStatus -ne 0 ] ; then break ; fi 
     1091 
    10411092  done 
    10421093 
    1043   rm ${_rSnapList} >/dev/null 2>/dev/null 
     1094  if [ -e "${_rSnapList}" ] ; then rm ${_rSnapList}; fi 
     1095  if [ -e "${_rDsetList}" ] ; then rm ${_rDsetList}; fi 
    10441096 
    10451097  cleanup_iscsi 
     
    10731125} 
    10741126 
     1127do_zfs_send_now() { 
     1128 
     1129    # Do the send/recv now 
     1130    zSEND="zfs send ${1}" 
     1131    zRCV="${CMDPREFIX} zfs receive $2" 
     1132    queue_msg "Using ZFS send command:\n$zSEND | $zRCV\n\n" 
     1133 
     1134    # Start up our process 
     1135    $zSEND 2>${REPLOGSEND} | $zRCV >${REPLOGRECV} 2>${REPLOGRECV} 
     1136    local rtnCode=$? 
     1137 
     1138    queue_msg "ZFS SEND LOG:\n--------------\n" "${REPLOGSEND}" 
     1139    queue_msg "ZFS RCV LOG:\n--------------\n" "${REPLOGRECV}" 
     1140 
     1141    if [ $rtnCode -ne 0 ] ; then return $rtnCode ; fi 
     1142 
     1143    if [ -n "$lastSENDPART" ] ; then 
     1144      zfs set lpreserver-part:${REPHOST}=' ' ${dset}@$lastSENDPART 
     1145    fi 
     1146    zfs set lpreserver-part:${REPHOST}=LATEST ${dset}@${3} 
     1147 
     1148    return 0 
     1149} 
     1150 
    10751151save_rep_props() { 
    1076   # Unset the remote mountpoint= properties 
    1077   unset_mount_props "$DATASET" 
    10781152 
    10791153  # If we are not doing a recursive backup / complete dataset we can skip this 
     
    14351509 
    14361510  # Now lets mark none of our datasets as replicated 
    1437   lastSEND=`zfs get -d 1 lpreserver:${REPHOST} ${LDATA} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1` 
    1438   if [ -n "$lastSEND" ] ; then 
    1439      zfs set lpreserver:${REPHOST}=' ' ${LDATA}@$lastSEND 
    1440   fi 
     1511  while : 
     1512  do 
     1513    lastSEND=`zfs get -d 1 lpreserver:${REPHOST} ${LDATA} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1` 
     1514    if [ -n "$lastSEND" ] ; then 
     1515       zfs set lpreserver:${REPHOST}=' ' ${LDATA}@$lastSEND 
     1516       continue 
     1517    fi 
     1518    break 
     1519  done 
    14411520 
    14421521  build_dset_list "$LDATA" "rep" 
    14431522  for dset in ${DSETS} 
    14441523  do 
    1445     lastSENDPART=`zfs get -d 1 lpreserver-part:${REPHOST} ${dset} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1` 
    1446     if [ -n "$lastSENDPART" ] ; then 
    1447        zfs set lpreserver-part:${REPHOST}=' ' ${dset}@$lastSENDPART 
    1448     fi 
     1524    while : 
     1525    do 
     1526      lastSENDPART=`zfs get -d 1 lpreserver-part:${REPHOST} ${dset} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1` 
     1527      if [ -n "$lastSENDPART" ] ; then 
     1528        zfs set lpreserver-part:${REPHOST}=' ' ${dset}@$lastSENDPART 
     1529        continue 
     1530      fi 
     1531      break 
     1532    done 
    14491533  done 
    14501534 
Note: See TracChangeset for help on using the changeset viewer.