ZFS Networker

From Lolly's Wiki
Revision as of 17:39, 25 November 2021 by Lollypop (talk | contribs) (Text replacement - "</source" to "</syntaxhighlight")
Jump to navigationJump to search

Backup Networker Backup

Backup of ZFS snapshots on Solaris Cluster with Legato/EMC Networker

This describes how to setup a backup of the Solaris Cluster resource group named sample-rg.

The structure of my RGs is always:

RG:                <name>-rg
ZFS-HASP:          <name>-hasp-zfs-res
Logical Host:      <name>-lh-res
Logical Host Name: <name>-lh
ZPOOL:             <name>_pool

I used the bash as shell.

Define variables used in the following command lines

<source lang=bash>

  1. NAME=sample
  2. RGname=${NAME}-rg
  3. NetworkerGroup=$(echo ${NAME} | tr 'a-z' 'A-Z' )
  4. ZPOOL=${NAME}_pool
  5. ZPOOL_BASEDIR=/local/${RGname}

</syntaxhighlight>

Define a resource for Networker

What we need now is a resource definition in our Networker directory like this: <source lang=bash>

  1. mkdir /nsr/{bin,log,res}
  2. cat > /nsr/res/${NetworkerGroup}.res <<EOF

type: savepnpc; precmd: "/nsr/bin/nsr_snapshot.sh pre >/nsr/log/networker_precmd.log 2>&1"; pstcmd: "/nsr/bin/nsr_snapshot.sh pst >/nsr/log/networker_pstcmd.log 2>&1"; timeout: "08:00am"; abort precmd with group: Yes; EOF </syntaxhighlight>

The pre-/pstcmd-script

!!!THIS CODE IS UNTESTED DO NOT USE THIS!!!

!!!THIS JUST AN EXAMPLE!!! <source lang=bash>

  1. !/bin/bash

cmd_option=$1 export cmd_option

SNAPSHOT_NAME="nsr" BASE_LOG_DIR="/nsr/logs" NSR_BACKUP_CLONE="nsr_backup"

  1. Commands

ZFS_CMD="/usr/sbin/zfs" ZPOOL_CMD="/usr/sbin/zpool" ZLOGIN_CMD="/usr/sbin/zlogin" ZONECFG_CMD="/usr/sbin/zonecfg" SVCS_CMD="/usr/sbin/svcs" SVCADM_CMD="/usr/sbin/svcadm" DF_CMD="/usr/bin/df" RM_CMD="/usr/bin/rm" AWK_CMD="/usr/bin/nawk" MKNOD_CMD="/usr/sbin/mknod" XARGS_CMD="/usr/bin/xargs" PARGS_CMD="/usr/bin/pargs" PTREE_CMD="/usr/bin/ptree" CLRS_CMD="/usr/cluster/bin/clrs" CLRG_CMD="/usr/cluster/bin/clrg" CLRT_CMD="/usr/cluster/bin/clrt" BASENAME_CMD="/usr/bin/basename" GETENT_CMD="/usr/bin/getent" SCHA_RESOURCE_GET_CMD="/usr/cluster/bin/scha_resource_get" WGET_CMD=/usr/sfw/bin/wget HOSTNAME_CMD="/usr/bin/uname -n"


  1. Subdir in ZFS where to put ZFS-config

ZFS_SETUP_SUBDIR="cluster_config" ZFS_CONFIG_FILE=ZFS_Setup.sh

  1. Oracle parameter

ORACLE_SID=SAMPLE ORACLE_USER=oracle

  1. Sophora parameter

SOPHORA_FMRI="svc:/cms/sophora:default" SOPHORA_USER=admin SOPHORA_PASS=password


GLOBAL_LOGFILE=${BASE_LOG_DIR}/$(${BASENAME_CMD} $0 .sh).log

  1. For all but get_slaves redirect output to log

case ${cmd_option} in get_slaves)

 ;;
  • )
 exec >>${GLOBAL_LOGFILE} 2>&1
 ;;

esac

function print_option () {

 option=$1; shift
 # now process line
 while [ $# -gt 0 ]
 do
   case $1 in
   ${option})
       echo $2
       shift
       shift
       ;;
   *)
       shift
       ;;
   esac
 done

}

function sophora_startup () {

 SOPHORA_ZONE=$1 # Zone for zlogin
 SOPHORA_FMRI=$2 # FMRI for svcadm
 print_log ${LOGFILE} "Starting sophora in ${SOPHORA_ZONE}..."
 ${ZLOGIN_CMD} ${SOPHORA_ZONE} ${SVCADM_CMD} enable ${SOPHORA_FMRI}

}

function sophora_shutdown () {

 SOPHORA_ZONE=$1 # Zone for zlogin
 SOPHORA_FMRI=$2 # FMRI for svcadm
 print_log ${LOGFILE} "Shutting down sophora in ${SOPHORA_ZONE}..."
 ${ZLOGIN_CMD} ${SOPHORA_ZONE} ${SVCADM_CMD} disable -t ${SOPHORA_FMRI}

}

function sophora_get_slaves () {

 SOPHORA_ZONE=$1 # Zone for zlogin
 SOPHORA_PORT=$2 # Sophora port at localhost
 SOPHORA_USER=$3 # Sophora admin user
 SOPHORA_PASS=$4 # Sophora admin port
 ${ZLOGIN_CMD} ${SOPHORA_ZONE} \
   ${WGET_CMD} \
     -qO- \
     --no-proxy \
     --http-user=${SOPHORA_USER} \
     --http-password=${SOPHORA_PASS} \
     "http://localhost:${SOPHORA_PORT}/content-api/servers/?replicationMode=SLAVE" | \
   ${AWK_CMD} '

function get_param(param,name){

 name="\""name"\"";
 count=split(param,tupel,/,/);
 for(i=1;i<=count;i++){
   split(tupel[i],part,/:/);
   if(part[1]==name){
     gsub(/\"/,"",part[2]);return part[2];
   }
 }

} {

 json=$0;
 gsub(/(\[\{|\}\])/,"",json);
 elements=split(json,array,/\},\{/);
 for(element=1;element<=elements;element++){
   print get_param(array[element],"hostname");
 }

}' | ${XARGS_CMD} -n 1 -i ${BASENAME_CMD} {} .server.de

}

function get_zone_hostname () {

 ${ZLOGIN_CMD} $1 ${HOSTNAME_CMD}

}

function print_log () {

 LOGFILE=$1 ; shift
 if [ $# -gt 0 ]
 then
   printf "%s (%s): %s\n" "$(date '+%Y%m%d %H:%M:%S')" "${cmd_option}" "$*" >> ${LOGFILE}
 else
   #printf "%s (%s): " "$(date '+%Y%m%d %H:%M:%S')" "${cmd_option}" >> ${LOGFILE}
   while read data
   do
     printf "%s (%s): %s\n" "$(date '+%Y%m%d %H:%M:%S')" "${cmd_option}" "${data}" >> ${LOGFILE}
   done
 fi

}

function dump_zfs_config {

 ZPOOL=$1
 OUTPUT_FILE=$2
 printf "\n\n# Create ZPool ${ZPOOL} with size $(${ZPOOL_CMD} list -Ho size ${ZPOOL}):\n\n" >> ${OUTPUT_FILE}
 ${ZPOOL_CMD} status ${ZPOOL} | ${AWK_CMD} '/config:/,/errors:/{if(/NAME/){getline; printf "Zpool structure of %s:\n\nzpool create %s",$1,$1; getline ; device=0; while(!/^$/ && !/errors:/){gsub(/mirror-[0-9]+/,"mirror",$1);gsub(/logs/,"log",$1);gsub(/(\/dev\/(r)*dsk\/)*c[0-9]+t[0-9A-F]+d[0-9]+(s[0-9]+)*/,"<device"device">",$1);if(/device/)device++;printf " %s",$1 ; getline}};printf "\n" ;}' >> ${OUTPUT_FILE}
 printf "\n\n# Create ZFS\n\n"   >> ${OUTPUT_FILE}
 ${ZFS_CMD} list -Hrt filesystem -o name,origin ${ZPOOL} | ${AWK_CMD} -v zfs_cmd=${ZFS_CMD} 'NR>1 && $2=="-"{print zfs_cmd,"create -o mountpoint=none",$1}' >> ${OUTPUT_FILE}
 printf "\n\n# Set ZFS values\n\n" >> ${OUTPUT_FILE}
 ${ZFS_CMD} get -s local -Ho name,property,value -pr all ${ZPOOL} | ${AWK_CMD} -v zfs_cmd=${ZFS_CMD} '$2!="readonly"{printf "%s set -p %s=%s %s\n",zfs_cmd,$2,$3,$1}' >> ${OUTPUT_FILE}

}

function dump_cluster_config {

 RG=$1
 OUTPUT_DIR=$2
 ${RM_CMD} -f ${OUTPUT_DIR}/${RG}.clrg_export.xml
 ${CLRG_CMD} export -o ${OUTPUT_DIR}/${RG}.clrg_export.xml ${RG}
 for RES in $(${CLRS_CMD} list -g ${RG})
 do
   ${RM_CMD} -f ${OUTPUT_DIR}/${RES}.clrs_export.xml
   ${CLRS_CMD} export -o ${OUTPUT_DIR}/${RES}.clrs_export.xml ${RES}
 done
 # Commands to recreate the RG
 COMMAND_FILE="${OUTPUT_DIR}/${RG}.ClusterCreateCommands.txt"
 printf "Recreate %s:\n%s create -i %s %s\n\n" "${RG}" "${CLRG_CMD}" "${OUTPUT_DIR}/${RG}.clrg_export.xml" "${RG}" > ${COMMAND_FILE}
 for RT in SUNW.LogicalHostname SUNW.HAStoragePlus SUNW.gds LGTO.clnt
 do
   for RT_VERSION in $(${CLRT_CMD} list | ${AWK_CMD} -v rt=${RT} '$1 ~ rt')
   do
     for RES in $(${CLRS_CMD} list -g ${RG} -t ${RT_VERSION})
     do
       if [ "_${RT}_" == "_SUNW.LogicalHostname_" ]
       then
         printf "Add the following entries to all nodes!!!:\n/etc/inet/hosts:\n" >> ${COMMAND_FILE}
         ${GETENT_CMD} hosts $(${CLRS_CMD} show -p HostnameList ${RES} | nawk '$1=="HostnameList:"{$1="";print}') >> ${COMMAND_FILE}
         printf "\n" >> ${COMMAND_FILE}
       fi
       printf "Recreate %s:\n%s create -i %s %s\n\n" "${RES}" "${CLRS_CMD}" "${OUTPUT_DIR}/${RES}.clrs_export.xml" "${RES}" >> ${COMMAND_FILE}
     done
   done
 done

}

function snapshot_pre {

 DB=$1
 DBUSER=$2
 if [ $# -eq 3 -a "_$3_" != "__" ]
 then
   ZONE=$3
   ZONE_CMD="${ZLOGIN_CMD} -l ${DBUSER} ${ZONE}"
   ZONE_BASE=$(/usr/sbin/zonecfg -z ${ZONE} info zonepath | ${AWK_CMD} '{print $NF;}')
   ZONE_ROOT="${ZONE_BASE}/root"
 else
   ZONE_ROOT=""
   ZONE_CMD="su - ${DBUSER} -c"
 fi
 if( ${ZONE_CMD} echo >/dev/null 2>&1 )
 then
   SCRIPT_NAME="tmp/.nsr-pre-snap-script.$$"
   # Create script inside zone
   cat >${ZONE_ROOT}/{SCRIPT_NAME} <<EOS
  1. !/bin/bash

DBDIR=\$(${AWK_CMD} -F':' -v ORACLE_SID=${ORACLE_SID} '\$1==ORACLE_SID {print \$2;}' /var/opt/oracle/oratab) \${DBDIR}/bin/sqlplus sys/${DBUSER} as sysdba << EOF create pfile from spfile; alter system archive log current; alter database backup controlfile to trace; alter database begin backup; EOF EOS

   chmod 755 ${ZONE_ROOT}/${SCRIPT_NAME}
   ${ZONE_CMD} /${SCRIPT_NAME} 2>&1 | print_log ${LOGFILE}
   rm -f ${ZONE_ROOT}/${SCRIPT_NAME}
 fi

}


function snapshot_pst {

 DB=$1
 DBUSER=$2
 if [ $# -eq 3 -a "_$3_" != "__" ]
 then
   ZONE=$3
   ZONE_CMD="${ZLOGIN_CMD} -l ${DBUSER} ${ZONE}"
   ZONE_BASE=$(/usr/sbin/zonecfg -z ${ZONE} info zonepath | ${AWK_CMD} '{print $NF;}')
   ZONE_ROOT="${ZONE_BASE}/root"
 else
   ZONE_ROOT=""
   ZONE_CMD="su - ${DBUSER} -c"
 fi
 if( ${ZONE_CMD} echo >/dev/null 2>&1 )
 then
   SCRIPT_NAME="tmp/.nsr-pre-snap-script.$$"
   # Create script inside zone
   cat >${ZONE_ROOT}/{SCRIPT_NAME} <<EOS
  1. !/bin/bash

DBDIR=\$(${AWK_CMD} -F':' -v ORACLE_SID=${ORACLE_SID} '\$1==ORACLE_SID {print \$2;}' /var/opt/oracle/oratab) \${DBDIR}/bin/sqlplus sys/${DBUSER} as sysdba << EOF alter database end backup; alter system archive log current; EOF EOS

   chmod 755 ${ZONE_ROOT}/${SCRIPT_NAME}
   ${ZONE_CMD} /${SCRIPT_NAME} 2>&1 | print_log ${LOGFILE}
   rm -f ${ZONE_ROOT}/${SCRIPT_NAME}
 fi

}

function snapshot_create {

 ZPOOL=$1
 SNAPSHOT_NAME=$2
 RES="$(${CLRS_CMD} show -p ZPools | ${AWK_CMD} -v pool=${ZPOOL} '/^Resource:/{res=$NF;}$NF ~ pool{print res;}')"
 # Because of problems with unmounting during cluster monitoring disable montoring for this step
 print_log ${LOGFILE} "Telling Cluster not to monitor ${RES}"
 if [ "_${RES}_" != "__" ]
 then
   ${CLRS_CMD} unmonitor ${RES}
 fi
 print_log ${LOGFILE} "Create ZFS snapshot -r ${ZPOOL}@${SNAPSHOT_NAME}"
 ${ZFS_CMD} snapshot -r ${ZPOOL}@${SNAPSHOT_NAME}
 for zfs_snapshot in $(${ZFS_CMD} list -Ho name -t snapshot -r ${ZPOOL} | grep ${SNAPSHOT_NAME})
 do
   ${ZFS_CMD} clone -o readonly=on ${zfs_snapshot} ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE}
   ${ZFS_CMD} mount ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE} 2>/dev/null
   if [ "_$(${ZFS_CMD} get -Ho value mounted ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE})_" == "_yes_" ]
   then
  1. echo /usr/sbin/save -s ${SERVER_NAME} -g ${GROUP_NAME} -LL -m ${CLIENT_NAME} $(${ZFS_CMD} get -Ho value mountpoint ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE})
     ${ZFS_CMD} list -Ho creation,name ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE} |  print_log ${LOGFILE}
   fi
 done
 print_log ${LOGFILE} "Telling Cluster to monitor ${RES} again"
 if [ "_${RES}_" != "__" ]
 then
   sleep 1
   ${CLRS_CMD} monitor ${RES}
 fi

}

function snapshot_destroy {

 ZPOOL=$1
 SNAPSHOT_NAME=$2
 RES="$(${CLRS_CMD} show -p ZPools | ${AWK_CMD} -v pool=${ZPOOL} '/^Resource:/{res=$NF;}$NF ~ pool{print res;}')"
 # Because of problems with unmounting during cluster monitoring disable montoring for this step
 print_log ${LOGFILE} "Telling Cluster not to monitor ${RES}"
 if [ "_${RES}_" != "__" ]
 then
   ${CLRS_CMD} unmonitor ${RES}
 fi
 if (${ZFS_CMD} list -t snapshot ${ZPOOL}@${SNAPSHOT_NAME} > /dev/null)
 then
   for zfs_snapshot in $(${ZFS_CMD} list -Ho name -t snapshot -r ${ZPOOL} | grep ${SNAPSHOT_NAME})
   do
     if [ "_$(${ZFS_CMD} get -Ho value mounted ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE})_" == "_yes_" ]
     then
       print_log ${LOGFILE} "Unmount ZFS clone ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE}"
       ${ZFS_CMD} unmount ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE}
     fi
     # If this is a clone of ${zfs_snapshot}, then destroy it
     if [ "_$(${ZFS_CMD} list -Ho origin ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE})_" == "_${zfs_snapshot}_" ]
     then
       print_log ${LOGFILE} "Destroy ZFS clone ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE}"
       ${ZFS_CMD} destroy ${zfs_snapshot/@*/}/${NSR_BACKUP_CLONE}
     fi
   done
   print_log ${LOGFILE} "Destroy ZFS snapshot -r ${ZPOOL}@${SNAPSHOT_NAME}"
   ${ZFS_CMD} destroy -r ${ZPOOL}@${SNAPSHOT_NAME}
 fi
 print_log ${LOGFILE} "Telling Cluster to monitor ${RES} again"
 if [ "_${RES}_" != "__" ]
 then
   ${CLRS_CMD} monitor ${RES}
 fi

}

function usage {

 echo "Usage: $0 (pre|pst)"
 echo "Usage: $0 init <ZPool-Name>"
 echo "Usage: $0 initall"
 echo "Usage: $0 dump <ZPool-Name> <Output-File>"
 exit 1

}

case ${cmd_option} in pre|pst)

 case ${cmd_option} in
 pre)
   # Get commandline from parent pid
   # pre /usr/sbin/savepnpc -c <NetworkerClient> -s <NetworkerServer> -g <NetworkerGroup> -LL
   print_log ${GLOBAL_LOGFILE} "Begin (${cmd_option}) Called from $(${PTREE_CMD} $$ | ${AWK_CMD} '/savepnpc/{print $0}')"
   pid=$(${PTREE_CMD} $$ | ${AWK_CMD} '/savepnpc/{print $1}')
   ;;
 pst)
   # Get commandline from parent pid
   # pst /usr/bin/pstclntsave -s <NetworkerServer> -g <NetworkerGroup> -c <NetworkerClient>
   print_log ${GLOBAL_LOGFILE} "Begin (${cmd_option}) Called from $(${PTREE_CMD} $$ | ${AWK_CMD} '/pstclntsave/{print $0}')"
   pid=$(${PTREE_CMD} $$ | ${AWK_CMD} '/pstclntsave/{print $1}')
   ${PTREE_CMD} $$ | print_log ${GLOBAL_LOGFILE}
   print_log ${GLOBAL_LOGFILE} "(${cmd_option}) PID=${pid}"
   ;;
 esac
 commandline="$(${PARGS_CMD} -c ${pid} | ${AWK_CMD} -F':' '$1 ~ /^argv/{printf $2}END{print;}')"
 # Called from backupserver use -c
 CLIENT_NAME=$(print_option -c ${commandline})
 # If called from cmdline use -m
 CLIENT_NAME=${CLIENT_NAME:-$(print_option -m ${commandline})}
 # Last resort pre/post
 CLIENT_NAME=${CLIENT_NAME:-${cmd_option}}
 SERVER_NAME=$(print_option -s ${commandline})
 GROUP_NAME=$(print_option -g ${commandline})
 LOGFILE=${BASE_LOG_DIR}/${CLIENT_NAME}.log
 print_log ${LOGFILE} "Called from ${commandline}"
 named_pipe=/tmp/.named_pipe.$$
 # Delete named pipe on exit
 trap "rm -f ${named_pipe}" EXIT
 # Create named pipe
 ${MKNOD_CMD} ${named_pipe} p
 # Read from named pipe and send it to print_log
 tee <${named_pipe} | print_log ${LOGFILE}&
 # Close STDOUT & STDERR
 exec 1>&-
 exec 2>&-
 # Redirect them to named pipe
 exec >${named_pipe} 2>&1
 print_log ${LOGFILE} "Begin backup of ${CLIENT_NAME}"
 # Get resource name from hostname
 LH_RES=$(${CLRS_CMD} show -t SUNW.LogicalHostname -p HostnameList | ${AWK_CMD} -v Hostname="${CLIENT_NAME}" '/^Resource:/{res=$NF} /HostnameList:/ {for(i=2;i<=NF;i++){if($i == Hostname){print res}}}')
 print_log ${LOGFILE} "LogicalHostname of ${CLIENT_NAME} is ${LH_RES}"
 # Get ressourceGroup name from ressource name
 RG=$(${SCHA_RESOURCE_GET_CMD} -O GROUP -R ${LH_RES})
 print_log ${LOGFILE} "RessourceGroup of ${LH_RES} is ${RG}"


 ZPOOLS=$(${CLRS_CMD} show -g ${RG} -p Zpools  | ${AWK_CMD} '$1=="Zpools:"{$1="";print $0}')
 print_log ${LOGFILE} "ZPools used in ${RG}: ${ZPOOLS}"
 Start_command=$(${CLRS_CMD} show -p Start_command -g ${RG} | ${AWK_CMD} -F ':' '$1 ~ /Start_command/ && $2 ~ /sczbt/')
 print_log ${LOGFILE} "sczbt Start_command is: ${Start_command}"
 sczbt_config=$(print_option -P ${Start_command})/sczbt_$(print_option -R ${Start_command})
 print_log ${LOGFILE} "sczbt_config is ${sczbt_config}"
 ZONE=$(${AWK_CMD} -F '=' '$1=="Zonename"{gsub(/"/,"",$2);print $2}' ${sczbt_config})
 print_log ${LOGFILE} "Zone from ${sczbt_config} is ${ZONE}"
 ;;

init)

 LOGFILE=${BASE_LOG_DIR}/init.log
 if [ $# -ne 2 ]
 then
   echo "Wrong count of parameters."
   echo "Use $0 init <ZPool-Name>"
   exit 1
 fi
 ZPOOL=$2
 print_log ${GLOBAL_LOGFILE} "Begin (${cmd_option}) of zpool ${ZPOOL}"
 print_log ${LOGFILE} "Begin init of zpool ${ZPOOL}"
 ;;

initall)

 LOGFILE=${BASE_LOG_DIR}/initall.log
 print_log ${GLOBAL_LOGFILE} "Begin (${cmd_option})"
 ;;

get_slaves)

 if [ $# -ne 5 ]
 then
   echo "Wrong count of parameters."
   echo "Use $0 get_slaves <Zone-Name> <Sophora-Port> <Sophora-Adminuser> <Sophora-Password>"
   exit 1
 fi
 echo "Slave node(s): $(sophora_get_slaves $2 $3 $4 $5)"
 exit 0
 ;;

esac

case ${cmd_option} in dump_cluster)

 if [ $# -ne 3 ]
 then
   echo "Wrong count of parameters."
   echo "Use $0 dump_cluster <Ressource_Group> <DIR>"
   exit 1
 fi
 dump_cluster_config $2 $3
 ;;

dump)

 if [ $# -ne 3 ]
 then
   echo "Wrong count of parameters."
   echo "Use $0 dump <ZPool-Name> <File>"
   exit 1
 fi
 dump_zfs_config $2 $3
 ;;

init)

 snapshot_destroy ${ZPOOL} ${SNAPSHOT_NAME}
 snapshot_create  ${ZPOOL} ${SNAPSHOT_NAME}
 print_log ${LOGFILE} "End   init of zpool ${ZPOOL}"
 ;;

initall)

 for ZPOOL in $(${ZPOOL_CMD} list -Ho name)
 do
   if [ "_${ZPOOL}_" == "_rpool_" ]
   then
     continue
   fi
   print_log ${LOGFILE} "Begin init of zpool ${ZPOOL}"
   snapshot_destroy ${ZPOOL} ${SNAPSHOT_NAME}
   snapshot_create  ${ZPOOL} ${SNAPSHOT_NAME}
   print_log ${LOGFILE} "End   init of zpool ${ZPOOL}"
 done
 ;;

pre)

 for ZPOOL in ${ZPOOLS}
 do
   snapshot_destroy ${ZPOOL} ${SNAPSHOT_NAME}
 done
 # Shutdown Sophora?
 startup="No"
 case ${ZONE} in
 arcus-rg)
   # Staging zones
   #sophora_shutdown ${ZONE} ${SOPHORA_FMRI}
   #startup="Yes"
   ;;
 incus-zone|velum-zone)
   SOPHORA_ADMINPORT=1196
   # Master-/slave-zones
   is_slave=0
   zone_hostname=$(get_zone_hostname ${ZONE})
   for slave in $(sophora_get_slaves ${ZONE} ${SOPHORA_ADMINPORT} ${SOPHORA_USER} ${SOPHORA_PASS})
   do
     print_log ${LOGFILE} "_${slave}_ == _${zone_hostname}_?"
     if [ "_${slave}_" == "_${zone_hostname}_" ]
     then
       is_slave=1
     fi
   done
   if [ ${is_slave} -eq 1 ]
   then
     # Slave
     print_log ${LOGFILE} "Slave..."
     sophora_shutdown ${ZONE} ${SOPHORA_FMRI}
     startup="Yes"
   else
     # Master
     print_log ${LOGFILE} "Master... Not shutting down Sophora"
   fi
   ;;
 merkel-zone|brandt-zone|schmidt-zone)
   SOPHORA_ADMINPORT=1396
   # Master-/slave-zones
   is_slave=0
   zone_hostname=$(get_zone_hostname ${ZONE})
   for slave in $(sophora_get_slaves ${ZONE} ${SOPHORA_ADMINPORT} ${SOPHORA_USER} ${SOPHORA_PASS})
   do
     print_log ${LOGFILE} "_${slave}_ == _${zone_hostname}_?"
     if [ "_${slave}_" == "_${zone_hostname}_" ]
     then
       is_slave=1
     fi
   done
   if [ ${is_slave} -eq 1 ]
   then
     # Slave
     print_log ${LOGFILE} "Slave..."
     sophora_shutdown ${ZONE} ${SOPHORA_FMRI}
     startup="Yes"
   else
     # Master
     print_log ${LOGFILE} "Master... Not shutting down Sophora"
   fi
   ;;
 *)
   ;;
 esac
 # Find the dir to write down zfs-setup
 for ZPOOL in ${ZPOOLS}
 do
   if [ "_$(${ZFS_CMD} list -Ho name ${ZPOOL}/${ZFS_SETUP_SUBDIR} 2>/dev/null)_" != "__" ]
   then
     CONFIG_DIR=$(${ZFS_CMD} get -Ho value mountpoint ${ZPOOL}/${ZFS_SETUP_SUBDIR})
   else
     if [ -d $(${ZFS_CMD} get -Ho value mountpoint ${ZPOOL})/${ZFS_SETUP_SUBDIR} ]
     then
       CONFIG_DIR=$(${ZFS_CMD} get -Ho value mountpoint ${ZPOOL})/${ZFS_SETUP_SUBDIR}
     fi
   fi
   if [ -d ${CONFIG_DIR} ]
   then
     printf "# Settings for ZFS\n\n" > ${CONFIG_DIR}/${ZFS_CONFIG_FILE}
     ZONE_CONFIG_FILE=zonecfg_${ZONE}.export
     [ "_${ZONE}_" != "__" ] && ${ZONECFG_CMD} -z ${ZONE} export > ${CONFIG_DIR}/${ZONE_CONFIG_FILE}
   fi
 done
 # Save configs and create snapshots
 for ZPOOL in ${ZPOOLS}
 do
   if [ "_${CONFIG_DIR}_" != "__" ]
   then
     # Save zfs config
     dump_zfs_config ${ZPOOL} ${CONFIG_DIR}/${ZFS_CONFIG_FILE}
     # Save Clusterconfig
     dump_cluster_config ${RG} ${CONFIG_DIR}
   fi
   snapshot_create  ${ZPOOL} ${SNAPSHOT_NAME}
 done
 # Startup Sophora?
 if [ "_${startup}_" == "_Yes_" ]
 then
   sophora_startup ${ZONE} ${SOPHORA_FMRI}
 fi
 print_log ${LOGFILE} "End   backup of ${CLIENT_NAME}"
 ;;

pst)

 for ZPOOL in ${ZPOOLS}
 do
   snapshot_destroy ${ZPOOL} ${SNAPSHOT_NAME}
 done
 print_log ${LOGFILE} "End   backup of ${CLIENT_NAME}"
 ;;
  • )
 usage
 ;;

esac print_log ${GLOBAL_LOGFILE} "End (${cmd_option}) Called from:" ${PTREE_CMD} $$ | print_log ${GLOBAL_LOGFILE} exit 0 </syntaxhighlight>

MD5-Checksum <source lang=bash>

  1. digest -a md5 /nsr/bin/nsr_snapshot.sh

01be6677ddf4342b625b1aa59d805628 </syntaxhighlight>

!!!THIS CODE IS UNTESTED DO NOT USE THIS!!!

!!!THIS JUST AN EXAMPLE!!!

Restore/Recover

Set some variables

<source lang=bash> NSR_CLIENT="sample-cl" NSR_SERVER="nsr-server" ZPOOL="sample_pool"

RG="${NSR_CLIENT%-cl}-rg" ZONE="${NSR_CLIENT%-cl}-zone" </syntaxhighlight>

Look for a valid backup

<source lang=bash>

  1. /usr/sbin/mminfo -s ${NSR_SERVER} -o t -N /local/${RG}/cluster_config/nsr_backup

</syntaxhighlight>

Restore ZFS configuration

<source lang=bash>

  1. /usr/sbin/recover -s ${NSR_SERVER} -c ${NSR_CLIENT} -d /tmp -a /local/${RG}/cluster_config/nsr_backup/ZFS_Setup.sh

</syntaxhighlight> Look into file /tmp/ZFS_Setup.sh which should look like this: <source lang=bash>

  1. Create ZPool sample_pool with size 1.02T:

Zpool structure of sample_pool: zpool create sample_pool mirror <device0> <device1>

  1. Create ZFS

/usr/sbin/zfs create -o mountpoint=none sample_pool/app /usr/sbin/zfs create -o mountpoint=none sample_pool/cluster_config /usr/sbin/zfs create -o mountpoint=none sample_pool/data1 /usr/sbin/zfs create -o mountpoint=none sample_pool/data2 /usr/sbin/zfs create -o mountpoint=none sample_pool/home /usr/sbin/zfs create -o mountpoint=none sample_pool/log /usr/sbin/zfs create -o mountpoint=none sample_pool/usr_local /usr/sbin/zfs create -o mountpoint=none sample_pool/zone

  1. Set ZFS values

/usr/sbin/zfs set -p reservation=104857600 sample_pool /usr/sbin/zfs set -p mountpoint=none sample_pool /usr/sbin/zfs set -p mountpoint=/local/sample-rg/app sample_pool/app /usr/sbin/zfs set -p mountpoint=/local/sample-rg/cluster_config sample_pool/cluster_config /usr/sbin/zfs set -p mountpoint=/local/sample-rg/data1 sample_pool/data1 /usr/sbin/zfs set -p mountpoint=/local/sample-rg/data2 sample_pool/data2 /usr/sbin/zfs set -p mountpoint=/local/sample-rg/home sample_pool/home /usr/sbin/zfs set -p mountpoint=/local/sample-rg/log sample_pool/log /usr/sbin/zfs set -p mountpoint=/local/sample-rg/usr_local sample_pool/usr_local /usr/sbin/zfs set -p mountpoint=/local/sample-rg/zone sample_pool/zone /usr/sbin/zfs set -p zpdata:zn=sample-zone sample_pool/zone /usr/sbin/zfs set -p zpdata:rbe=S10_U9 sample_pool/zone /usr/sbin/zfs set -p mountpoint=/local/sample-rg/zone-zfsBE_20121105 sample_pool/zone-zfsBE_20121105 /usr/sbin/zfs set -p zoned=off sample_pool/zone-zfsBE_20121105 /usr/sbin/zfs set -p canmount=on sample_pool/zone-zfsBE_20121105 /usr/sbin/zfs set -p zpdata:zn=sample-zone sample_pool/zone-zfsBE_20121105 /usr/sbin/zfs set -p zpdata:rbe=S10_U9 sample_pool/zone-zfsBE_20121105 </syntaxhighlight> Mount the needed ZFS filesystems.

Restore zone configuration

<source lang=bash>

  1. /usr/sbin/recover -s ${NSR_SERVER} -c ${NSR_CLIENT} -d /tmp -a /local/${RG}/cluster_config/nsr_backup/zonecfg_${ZONE}.export
  2. zonecfg -z ${ZONE} -f /tmp/zonecfg_${ZONE}.export
  3. zonecfg -z ${ZONE} info

</syntaxhighlight>

Restore cluster configuration

<source lang=bash>

  1. /usr/sbin/recover -s ${NSR_SERVER} -c ${NSR_CLIENT} -d /tmp -a /local/${RG}/cluster_config/nsr_backup/*_export.xml
  2. /usr/sbin/recover -s ${NSR_SERVER} -c ${NSR_CLIENT} -d /tmp -a /local/${RG}/cluster_config/nsr_backup/*.ClusterCreateCommands.txt
  3. /usr/bin/perl -pi -e "s#/local/${RG}/cluster_config/nsr_backup/#/tmp/#g" /tmp/${RG}.ClusterCreateCommands.txt

</syntaxhighlight>

Follow the instructions in /tmp/${RG}.ClusterCreateCommands.txt: <source lang=bash> Recreate sample-rg: /usr/cluster/bin/clrg create -i /tmp/sample-rg.clrg_export.xml sample-rg

Add the following entries to all nodes!!!: /etc/inet/hosts: 10.29.7.96 sample-cl

Recreate sample-lh-res: /usr/cluster/bin/clrs create -i /tmp/sample-lh-res.clrs_export.xml sample-lh-res

Recreate sample-hasp-zfs-res: /usr/cluster/bin/clrs create -i /tmp/sample-hasp-zfs-res.clrs_export.xml sample-hasp-zfs-res

Recreate sample-emctl-res: /usr/cluster/bin/clrs create -i /tmp/sample-emctl-res.clrs_export.xml sample-emctl-res

Recreate sample-oracle-res: /usr/cluster/bin/clrs create -i /tmp/sample-oracle-res.clrs_export.xml sample-oracle-res

Recreate sample-zone-res: /usr/cluster/bin/clrs create -i /tmp/sample-zone-res.clrs_export.xml sample-zone-res

Recreate sample-nsr-res: /usr/cluster/bin/clrs create -i /tmp/sample-nsr-res.clrs_export.xml sample-nsr-res </syntaxhighlight>

Registering new resource type LGTO.clnt

1. Install Solaris client package LGTOclnt 2. Register new resource type in cluster. One one node do: <source lang=bash>

  1. clrt register -f /usr/sbin/LGTO.clnt.rtr LGTO.clnt

</syntaxhighlight> Now you have a new resource type LGTO.clnt in your cluster.

Create client resource of type LGTO.clnt

So I use scripts like this: <source lang=bash>

  1. RGname=sample-rg
  2. clrs create \
 -t LGTO.clnt \
 -g ${RGname} \
 -p Resource_dependencies=$(basename ${RGname} -rg)-hasp-zfs-res \
 -p clientname=$(basename ${RGname} -rg)-lh \
 -p Network_resource=$(basename ${RGname} -rg)-lh-res \
 -p owned_paths=${ZPOOL_BASEDIR} \
 $(basename ${RGname} -rg)-nsr-res

</syntaxhighlight>

This expands to: <source lang=bash>

  1. clrs create \
 -t LGTO.clnt \
 -g sample-rg \
 -p Resource_dependencies=sample-hasp-zfs-res \
 -p clientname=sample-lh \
 -p Network_resource=sample-lh-res \
 -p owned_paths=/local/sample-rg \
 sample-nsr-res

</syntaxhighlight>

Now we have a client name to which we can connect to: sample-lh