#!/bin/bash ORIGINAL_ARGS=("$@") # Includes . $(miniade) || { echo "${0##*/}: ERROR: miniade failed (hint: run 'miniade' to see error)" >&2; exit 1; } # Configurable stuff # Other globals BASE_DEVICE_MINOR=0 BASE_TCP_PORT=8790 LVM_VG_NAME=vg0 ZPOOL_NAME=zpool0 main() { local MY_ARGS local PROGNAME # Defaults for options REMOTE_HOST= TCP_PORT= VOL_NAME= VOL_SIZE= VOL_CREATION_MODE=lvm # Process options special_opts_handler() { case $1 in --name=*) VOL_NAME=${1#*=} ;; --size=*) VOL_SIZE=${1#*=} ;; --name1=*) PRIMARY_UNAME=${1#*=} ;; --name2=*) SECONDARY_UNAME=${1#*=} ;; --ip1=*) PRIMARY_IPADDR=${1#*=} ;; --ip2=*) SECONDARY_IPADDR=${1#*=} ;; --remote=*) REMOTE_HOST=${1#*=} ;; --tcp-port=*) TCP_PORT=${1#*=} ;; --vg=*) VOL_CREATION_MODE=lvm LVM_VG_NAME=${1#*=} ;; --zpool=*) VOL_CREATION_MODE=zfs ZPOOL_NAME=${1#*=} ;; --dev=*) VOL_CREATION_MODE=none DEV_PATH=${1#*=} ;; *) return 1 ;; esac } miniade_process_options --help-handler=help --special-opts-handler=special_opts_handler MY_ARGS "$@" && set -- "${MY_ARGS[@]}" # Process arguments [ $# = 0 ] || miniade_bad_usage # Sanity checks and derivations miniade_get_progname PROGNAME [[ $VOL_CREATION_MODE =~ ^(lvm|zfs|none)$ ]] || miniade_bad_usage for VAR in VOL_NAME VOL_SIZE PRIMARY_UNAME SECONDARY_UNAME PRIMARY_IPADDR SECONDARY_IPADDR; do eval "[ \"X\$$VAR\" != X ]" || miniade_bad_usage done [ "X$REMOTE_HOST" = X ] || miniade_check_ssh_ok $REMOTE_HOST || miniade_error "$REMOTE_HOST: no unfettered ssh access" I_AM_PRIMARY_FLAG=$(if ip -o -4 addr | sed -rn 's/.*inet ([^\/]+).*/\1/p' | fgrep -xq $PRIMARY_IPADDR; then echo true; else echo false; fi) miniade_debug 10 "main: I_AM_PRIMARY_FLAG=$I_AM_PRIMARY_FLAG" HIGHEST_DEVICE_MINOR=$(cat /etc/drbd.d/*.res /dev/null 2>/dev/null | sed -nr "s/.*minor *([0-9]+).*/\\1/p" | sort -rn | head -1) case $HIGHEST_DEVICE_MINOR in '') DEVICE_MINOR=$BASE_DEVICE_MINOR ;; [0-9]*) DEVICE_MINOR=$((HIGHEST_DEVICE_MINOR+1)) ;; esac if [ "X$TCP_PORT" = X ]; then HIGHEST_TCP_PORT=$(cat /etc/drbd.d/*.res /dev/null 2>/dev/null | sed -nr "s/.*address .*:([1-9][0-9]*).*/\\1/p" | sort -rn | head -1) case $HIGHEST_TCP_PORT in '') TCP_PORT=$BASE_TCP_PORT ;; [1-9]*) TCP_PORT=$((HIGHEST_TCP_PORT+1)) ;; esac fi if [[ $VOL_SIZE =~ ^([1-9][0-9]*)([tgbTGB]?)$ ]]; then VOL_SIZE=${BASH_REMATCH[1]} VOL_SIZE_UNIT=${BASH_REMATCH[2]^^:-G} else miniade_error "$VOL_SIZE: invalid volume size (hint: format is [unit])" fi miniade_debug 10 "main: DEVICE_MINOR=$DEVICE_MINOR, TCP_PORT=$TCP_PORT" # Guts #echo "$(date --iso=seconds): $0" "${ORIGINAL_ARGS[@]}" >> $HISTFILE echo "#!/bin/bash" > /tmp/$PROGNAME.$$.sh if [ $VOL_CREATION_MODE = lvm ]; then miniade_info "$LVM_VG_NAME: checking VG exists ..." vgs $LVM_VG_NAME > /dev/null 2>&1 || miniade_error "$LVM_VG_NAME: not found (hint: run 'vgs $LVM_VG_NAME')" miniade_info "$VOL_NAME: checking LV doesn't exist already ..." LVS_STDERR=$(lvs --noheadings -o name /dev/$LVM_VG_NAME/$VOL_NAME 2>&1 > /dev/null) || true [[ $LVS_STDERR =~ Failed\ to\ find\ logical\ volume ]] || miniade_error "$VOL_NAME: LVs may exist already" miniade_info "$VOL_NAME: creating LV ..." # If you thought the right option not to be asked about wiping DRBD signatures # would be '--wipesignatures=y' then you thought wrong. Just use '--yes'. Sheesh. LVCREATE_CMDLINE="lvcreate --yes --size=$VOL_SIZE$VOL_SIZE_UNIT --name=$VOL_NAME $LVM_VG_NAME > /dev/null 2>&1" miniade_evaler "$LVCREATE_CMDLINE" echo "$LVCREATE_CMDLINE" >> /tmp/$PROGNAME.$$.sh DRBD_COMPONENT_DEVICE=/dev/$LVM_VG_NAME/$VOL_NAME elif [ $VOL_CREATION_MODE = zfs ]; then miniade_info "$ZPOOL_NAME: checking pool exists ..." zfs list $ZPOOL_NAME > /dev/null 2>&1 || miniade_error "$ZPOOL_NAME: not found (hint: run 'zfs list $ZPOOL_NAME')" miniade_info "$VOL_NAME: checking zvol doesn't exist already ..." ZFS_STDERR=$(zfs list $ZPOOL_NAME/$VOL_NAME 2>&1 > /dev/null) || true [[ $ZFS_STDERR =~ dataset\ does\ not\ exist ]] || miniade_error "$VOL_NAME: zvol may exist already" miniade_info "$VOL_NAME: creating zvol ..." ZFS_CMDLINE="zfs create -s -V $VOL_SIZE$VOL_SIZE_UNIT $ZPOOL_NAME/$VOL_NAME" miniade_evaler "$ZFS_CMDLINE" echo "$ZFS_CMDLINE" >> /tmp/$PROGNAME.$$.sh DRBD_COMPONENT_DEVICE=/dev/zvol/$ZPOOL_NAME/$VOL_NAME elif [ $VOL_CREATION_MODE = none ]; then DRBD_COMPONENT_DEVICE=$DEV_PATH fi miniade_info "$VOL_NAME: creating DRBD config ..." { echo "resource drbd_$VOL_NAME {" echo " protocol A;" echo " device /dev/drbd_$VOL_NAME minor $DEVICE_MINOR;" echo " meta-disk internal;" echo " disk $DRBD_COMPONENT_DEVICE;" echo " net {" echo " #allow-two-primaries;" echo " after-sb-0pri discard-zero-changes;" echo " after-sb-1pri discard-secondary;" echo " #after-sb-2pri disconnect;" echo " }" echo " on $PRIMARY_UNAME {" echo " address $PRIMARY_IPADDR:$TCP_PORT;" echo " }" echo " on $SECONDARY_UNAME {" echo " address $SECONDARY_IPADDR:$TCP_PORT;" echo " }" echo " handlers {" echo " before-resync-target \"/sbin/drbdsetup \$DRBD_MINOR secondary\";" echo " split-brain \"/usr/lib/drbd/notify-split-brain.sh root\";" echo " }" echo "}" } > /tmp/$PROGNAME.$$.res { echo "cat > /etc/drbd.d/$VOL_NAME.res <<'EOF'"; cat /tmp/$PROGNAME.$$.res; echo "EOF"; } >> /tmp/$PROGNAME.$$.sh miniade_evaler "mv /tmp/$PROGNAME.$$.res /etc/drbd.d/$VOL_NAME.res" miniade_info "$VOL_NAME: initialising device ..." miniade_evaler "drbdadm -- --force create-md drbd_$VOL_NAME > /dev/null 2>&1" echo "drbdadm -- --force create-md drbd_$VOL_NAME > /dev/null 2>&1" >> /tmp/$PROGNAME.$$.sh miniade_evaler "drbdadm up drbd_$VOL_NAME > /dev/null" echo "drbdadm up drbd_$VOL_NAME > /dev/null" >> /tmp/$PROGNAME.$$.sh if $I_AM_PRIMARY_FLAG; then miniade_evaler "drbdadm -- --overwrite-data-of-peer primary drbd_$VOL_NAME" else echo "drbdadm -- --overwrite-data-of-peer primary drbd_$VOL_NAME" >> /tmp/$PROGNAME.$$.sh fi if [ "X$REMOTE_HOST" != X ]; then miniade_evaler "ssh -T $REMOTE_HOST < /tmp/$PROGNAME.$$.sh" miniade_evaler "rm /tmp/$PROGNAME.$$.sh" else miniade_warning "/tmp/$PROGNAME.$$.sh: run this file on the other node" fi } help() { local PROGNAME miniade_get_progname PROGNAME echo "Usage: $PROGNAME [ ] [ --vg= | --zpool= ] [ --remote= ] [ --tcp-port= ] --name= --size=[MGT] --name1= --ip1= --name2= --ip2=" exit 0 } main "$@"