#!/bin/bash # $HeadURL$ $LastChangedRevision$ # Properties MY_ID=system_hardware_vm_virsh_storage_drbd PARENT_ID=system_hardware_vm_virsh_storage # Defaults for the questions we ask (should only used here) # Hooks # Support functions # Globals KNOWN_STORAGESERVER_HOSTNAMES="$KNOWN_VMSERVER_HOSTNAMES" STORAGESERVER_VOLUME_GROUP=vg0 DRBD_NIC=br2 loading main old_main() { local TARGET_HOSTNAME TARGET_ROOT_DISK_SIZE VMSERVER_HOSTNAME IGNORE_STATE_FILE_FLAG LIST_FILTER LIST_FORMAT MAILTO #local # Defaults for options VERBOSELEVEL=2 IGNORE_STATE_FILE_FLAG=false LIST_FORMAT=human LIST_FILTER=inprogress # Process options while [ "X$1" != X ]; do case $1 in # Application specific options --vmserver-hostname=*) VMSERVER_HOSTNAME=${1#*=} ;; --target-hostname=*) TARGET_HOSTNAME=${1#*=} ;; --target-root-disk-size=*) TARGET_ROOT_DISK_SIZE=${1#*=} ;; --mailto=*) MAILTO=${1#*=} ;; --ignore-state-file-flag=*) IGNORE_STATE_FILE_FLAG=${1#*=} ;; --list-format=*) LIST_FORMAT=${1#*=} ;; --list-filter=*) LIST_FILTER=${1#*=} ;; # General options --help|-h) usage 0 ;; --verbose|-v) VERBOSELEVEL=3 ;; -d) VERBOSELEVEL=$2; shift ;; --debug=*) VERBOSELEVEL=${1#*=} ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process arguments [ $# -ge 1 ] || usage MODE=$1; shift debug 10 "main: MODE=$MODE" # Sanity checks and derivations [ $MODE = get-rootfs-volname ] || validate_vars MODE || return $? # Guts case $MODE in create) create --vmserver-hostname=$VMSERVER_HOSTNAME --target-hostname=$TARGET_HOSTNAME --target-root-disk-size=$TARGET_ROOT_DISK_SIZE --mailto=$MAILTO "$@" || return $? ;; delete) delete --target-hostname=$TARGET_HOSTNAME --ignore-state-file-flag=$IGNORE_STATE_FILE_FLAG "$@" || return $? ;; list) list --list-format=$LIST_FORMAT --list-filter=$LIST_FILTER "$@" ;; list-finished) list_finished "$@" || return $? ;; get-rootfs-volname) get_rootfs_volname --vmserver-hostname=$VMSERVER_HOSTNAME --target-hostname=$TARGET_HOSTNAME --target-root-disk-size=$TARGET_ROOT_DISK_SIZE "$@" || return $? ;; purge) purge "$@" || return $? ;; *) usage ;; esac return 0 } loading create old_create() { local TARGET_HOSTNAME TARGET_ROOT_DISK_SIZE VMSERVER_HOSTNAME MAILTO # Process options while [ "X$1" != X ]; do case $1 in # Application specific options --vmserver-hostname=*) VMSERVER_HOSTNAME=${1#*=} ;; --target-hostname=*) TARGET_HOSTNAME=${1#*=} ;; --target-root-disk-size=*) TARGET_ROOT_DISK_SIZE=${1#*=} ;; --mailto=*) MAILTO=${1#*=} ;; # General options --) shift; break ;; -*) internal "create: $1: invalid option" ;; *) break ;; esac shift done # Process arguments [ $# = 0 ] || internal "create: $#: wrong arg count" # Sanity checks and derivations validate_vars TARGET_HOSTNAME VMSERVER_HOSTNAME TARGET_ROOT_DISK_SIZE MAILTO || return $? debug 10 "create: TARGET_HOSTNAME=$TARGET_HOSTNAME, VMSERVER_HOSTNAME=$VMSERVER_HOSTNAME, TARGET_ROOT_DISK_SIZE=$TARGET_ROOT_DISK_SIZE, MAILTO=$MAILTO" for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do check_ssh_access $STORAGESERVER_HOSTNAME || return $? done # Work out next available minor number (which doubles as port number offset) USED_MINOR_NUMBERS=$(for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do ssh -n $STORAGESERVER_HOSTNAME "cat /etc/drbd.d/*.res 2>/dev/null || true"; done | sed -n 's/.* minor \(.*\);/\1/p' | sort -un | paste -s -d' ') debug 10 "create: USED_MINOR_NUMBERS=\"$USED_MINOR_NUMBERS\"" for ((I=0; I<100; I++)); do debug 10 "create: checking if minor number $I available ..." MATCHED=false for USED_MINOR_NUMBER in $USED_MINOR_NUMBERS; do [ $I != $USED_MINOR_NUMBER ] || { MATCHED=true; break; } done $MATCHED || { NEXT_MINOR_NUMBER=$I; break; } done debug 10 "create: selected minor number $NEXT_MINOR_NUMBER" # Guts # Manage state file mkdir -p $VAR_DIR/$PROGNAME debug 10 "create: state file $VAR_DIR/$PROGNAME/$TARGET_HOSTNAME [$(ls -ld $VAR_DIR/$PROGNAME/$TARGET_HOSTNAME 2>&1)]" [ ! -f $VAR_DIR/$PROGNAME/$TARGET_HOSTNAME ] || { error "$TARGET_HOSTNAME: installation in progress"; return 1; } touch $VAR_DIR/$PROGNAME/$TARGET_HOSTNAME # Create LV for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do debug 5 "create: creating LV on $STORAGESERVER_HOSTNAME ..." CMDLINE="ssh -n $STORAGESERVER_HOSTNAME \"lvcreate --size ${TARGET_ROOT_DISK_SIZE}G --name $TARGET_HOSTNAME $STORAGESERVER_VOLUME_GROUP\"" debug 10 "create: calling [$CMDLINE] ..." LVCREATE_OUTPUT=$(eval "$CMDLINE" 2>&1) || { RC=1; error "lvcreate: failed (output was: $LVCREATE_OUTPUT)"; rm -f $VAR_DIR/$PROGNAME/$TARGET_HOSTNAME; return $RC; } done # Do common DRBD setup for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do debug 5 "create: writing config file $STORAGESERVER_HOSTNAME:/etc/drbd.d/$TARGET_HOSTNAME.res ..." { echo "resource $TARGET_HOSTNAME {" # xen live migration requires two primaries (see # http://www.drbd.org/users-guide-emb/s-xen-create-resource.html # but that means protocol C is required; attempting to use protocol # A produced the message '0: Failure: (139) Protocol C required' # when I tried to up the resource. So it's a toss-up: protocol c or # live migration. I want performance so I go for protocol C and no # live migration. Nope, it turns out that virsh also wants the # non-active node to have write access to the device. So it *must* # be dual primary and that means it must be protocl C. # # The saga continues: I keep getting split brain. So now I make one # primary max. So I lose live migrations ... okay, so be it. Let's see # if it works better now. echo " #net {" echo " # allow-two-primaries;" echo " #}" echo " protocol C;" echo " device /dev/drbd_$TARGET_HOSTNAME minor $NEXT_MINOR_NUMBER;" echo " meta-disk internal;" for STORAGESERVER_HOSTNAME2 in $KNOWN_STORAGESERVER_HOSTNAMES; do echo " on $STORAGESERVER_HOSTNAME2 {" hostnic2ipaddr $STORAGESERVER_HOSTNAME2 $DRBD_NIC IPADDR || return $? echo " address $IPADDR:$((7789+$NEXT_MINOR_NUMBER));" echo " disk /dev/$STORAGESERVER_VOLUME_GROUP/$TARGET_HOSTNAME;" echo " }" done echo "}" } | ssh $STORAGESERVER_HOSTNAME "cat > /etc/drbd.d/$TARGET_HOSTNAME.res" debug 5 "create: initialising metadata on $STORAGESERVER_HOSTNAME ..." # 'drbdadm create-md' can prompt for 'yes' twice. echo -e "yes\nyes" | ssh $STORAGESERVER_HOSTNAME "drbdadm create-md $TARGET_HOSTNAME" debug 5 "create: upping resource on $STORAGESERVER_HOSTNAME ..." ssh -n $STORAGESERVER_HOSTNAME "modprobe drbd; drbdadm up $TARGET_HOSTNAME" done # Do one-sided DRBD setup for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do [ $STORAGESERVER_HOSTNAME = $VMSERVER_HOSTNAME ] || continue debug 5 "create: making the resource primary on $STORAGESERVER_HOSTNAME ..." ssh -n $STORAGESERVER_HOSTNAME "drbdadm -- --overwrite-data-of-peer primary $TARGET_HOSTNAME" done for STORAGESERVER_HOSTNAME in $KNOWN_STORAGESERVER_HOSTNAMES; do [ $STORAGESERVER_HOSTNAME != $VMSERVER_HOSTNAME ] || continue debug 5 "create: making the resource secondary on $STORAGESERVER_HOSTNAME ..." ssh -n $STORAGESERVER_HOSTNAME "drbdadm secondary $TARGET_HOSTNAME" ssh -n $STORAGESERVER_HOSTNAME "drbdadm down $TARGET_HOSTNAME" send_email < ] { create | delete | list }" } | if [ $RC = 0 ]; then cat else cat >&2 fi exit $RC }