All other patches from the sequence remain unchanged. Repost of patch 6 based on comments from Joey to follow. Mike
Michael Burns
2009-Oct-01 17:54 UTC
[Ovirt-devel] [PATCH node] Added new menu for Multipath configuration
Also added new kernel command line arg to setup multipath. New menu takes user through mpath whitelisting and choosing an mpath device for installation. Signed-off-by: Michael Burns <mburns at redhat.com> --- scripts/ovirt-config-boot | 2 +- scripts/ovirt-config-storage | 190 +++++++++++++++++++++++++++++++++++++++- scripts/ovirt-config-uninstall | 8 ++ scripts/ovirt-early | 16 +++- 4 files changed, 208 insertions(+), 8 deletions(-) diff --git a/scripts/ovirt-config-boot b/scripts/ovirt-config-boot index fb9d74f..01c1821 100755 --- a/scripts/ovirt-config-boot +++ b/scripts/ovirt-config-boot @@ -219,7 +219,7 @@ set -e\ cp /sbin/dmsetup.static sbin/dmsetup cp /sbin/kpartx.static sbin/kpartx for M in /sbin/mpath_prio_*.static ; do - cp ${M} $/${M%%.static}; + cp ${M} .${M%%.static}; done fi diff --git a/scripts/ovirt-config-storage b/scripts/ovirt-config-storage index 7ced820..3829abb 100755 --- a/scripts/ovirt-config-storage +++ b/scripts/ovirt-config-storage @@ -130,6 +130,172 @@ check_partition_sizes() return $rc } +is_multipath_disabled() +{ + grep -q "^ *devnode \"\*\"" /etc/multipath.conf +} + +multipath_warn() +{ + sp=' ' + w='!!WARNING' + wb="$w"'!!' + w8="$w$w$w$w$w$w$w$w" + printf '%s!!\n' \ + "$w8" \ + "$w8" \ + "$wb$sp$w" \ + "$wb$sp$w" \ + "$wb Multipath Configurations should only be made $w" \ + "$wb on true multipath devices. Configuring any $w" \ + "$wb other devices may cause problems with your $w" \ + "$wb system. $w" \ + "$wb$sp$w" \ + "$wb Proceeding from this menu will erase all $w" \ + "$wb previous multipath configurations. $w" \ + "$wb$sp$w" \ + "$wb$sp$w" \ + "$w8" \ + "$w8" + +} + +abort_multipath() +{ + printf "Cleaning up multipath configuration\n">&2 + sed -i 's/^\s*wwid \*$/ devnode "*"/' /etc/multipath.conf + sed -i 's/^\s*wwid \w.*$//g' /etc/multipath.conf + service multipathd reload >&2 +} + +config_multipath_conf() +{ + ! is_multipath_disabled && abort_multipath + if [[ $OVIRT_MPATH = "ALL" ]]; then + sed -i 's/^\s*devnode ".*$/ #devnode "*"/' /etc/multipath.conf + else + sed -i 's/^\s*devnode ".*$/ wwid */' /etc/multipath.conf + test $(grep ^blacklist_exceptions /etc/multipath.conf | wc -l) = 0 \ + && printf "blacklist_exceptions {\n}" >> /etc/multipath.conf + local wwid="" + for d in $whitelisted + do + d=$(basename $d) + local scsi_id=$(scsi_id --whitelisted --device=/dev/$d) + if [[ -z $scsi_id ]]; then + echo "scsi_id failed for device /dev/$d. Not white listing." >&2 + else + wwid="${wwid} $scsi_id" + fi + done + wwid=$(echo $wwid | sed 's/ /\n/g' | sort -u) + for scsi_id in $wwid + do + sed -i "s/^blacklist_exceptions {$/blacklist_exceptions {\n wwid $scsi_id"/ /etc/multipath.conf + done + for d in $OVIRT_MPATH + do + sed -i "s/^blacklist_exceptions {$/blacklist_exceptions {\n wwid $d"/ /etc/multipath.conf + + done + fi + service multipathd reload >&2 + start_log + echo "Generated multipath.conf" + cat /etc/multipath.conf + echo "Output of multiatph -v6 command" + multipath -v6 + stop_log + return 0 +} + + +generate_whitelist() +{ + whitelisted="" + local devs=$devices + local PS3="Please select devices to add or remove from multipath whitelist: " + while true; do + local choices="" + for d in $devs + do + get_drive_size $d >&2 + if [[ $whitelisted =~ $d ]]; then + choices="$choices $d-whitelisted" + else + choices="$choices $d" + fi + done + + choices="$choices Done Abort" + select whitelist in $choices + do + test "$whitelist" = Abort && return 1 + test "$whitelist" = Done && return 0 + #first check if it is already whitelisted + #and remove from whitelist + if [[ $whitelist =~ "whitelisted" ]]; then + local tmp_whitelist="" + whitelist=${whitelist%-whitelisted} + for d in $whitelisted + do + test $d != $whitelist && tmp_whitelist="$tmp_whitelist $d" + done + whitelisted=$tmp_whitelist + #else add it to whitelist + else + whitelisted="$whitelisted $whitelist" + fi + break + done + done +} + +# Choose a multipathed device for installation +get_multipath_device() +{ + multipath_warn >&2 + local DRIVE_VAR=$1 + generate_whitelist + test $? = 1 && return 1 + config_multipath_conf + local count=0 + echo "Detecting Multipath Devices..." >&2 + while [ $count -lt 60 ] + do + test ! `ls /dev/mapper/mpath* 2> /dev/null | wc -l` = 0 && break + let count=$count+1 + sleep 1 + done + if [ `ls /dev/mapper/mpath* 2> /dev/null | wc -l` = 0 ]; then + echo "No Multipath devices found. Aborting...">&2 + abort_multipath + return 1 + fi + #need to provide a menu to choose a multipath device + while true + do + local choices="" + for dev in $(ls /dev/mapper/mpath* | egrep -v "p[0-9]+$") + do + choices="$choices $dev" + get_drive_size $dev >&2 + done + choices="$choices Abort" + local PS3="Select Multipath Device: " + select mpath_device in $choices + do + if [[ $mpath_device = Abort ]]; then + abort_multipath + return 1 + elif [[ -e $mpath_device ]]; then + eval $DRIVE_VAR=$mpath_device + return 0 + fi + done + done +} + # Find a usable/selected storage device. # If there are none, give a diagnostic and return nonzero. # If there is just one, e.g., /dev/sda, treat it as selected (see below). @@ -140,6 +306,7 @@ check_partition_sizes() get_dev_name() { local udi_list=$(hal-find-by-capability --capability storage) + local DRIVE_VAR=$1 if test -z "$udi_list"; then warn "ERROR: no usable storage devices detected" return 1 @@ -152,6 +319,9 @@ get_dev_name() local block_dev=$(hal-get-property --udi "$d" --key block.device) # Must start with a '/'. case $block_dev in + '') + #if block.device not defined, suppress warning + continue;; *' '*) # we use space as separator warn "block device name '$block_dev' contains space; skipping"; @@ -180,7 +350,7 @@ get_dev_name() # If there's only one device, use it. case $num_devices in 0) warn "ERROR: found no usable block device"; return 1;; - 1) echo "$devices"; return 0;; + 1) eval $DRIVE_VAR=$devices; return 0;; *) ;; # found more than one esac @@ -189,12 +359,13 @@ get_dev_name() for d in $devices; do get_drive_size $d >&2 done - local choices="$devices Abort" + local choices="$devices Multipath Abort" select device in $choices do test "$device" = Abort && return 1 + test "$device" = "Multipath" && get_multipath_device device; test -z "$device" && continue - echo "$device" + eval $DRIVE_VAR=$device return 0 done } @@ -202,7 +373,9 @@ get_dev_name() do_configure() { local name_and_size - DRIVE=$(get_dev_name) || return 0 + get_dev_name DRIVE + test ! -e $DRIVE && echo "Drive '$DRIVE' is not a valid drive" >&2 \ + && return 0 get_drive_size $DRIVE SPACE printf "\n\nPlease configure storage partitions.\n\n" @@ -539,6 +712,15 @@ CONFIG_SIZE=${OVIRT_VOL_CONFIG_SIZE:-$default_config_size} LOGGING_SIZE=${OVIRT_VOL_LOGGING_SIZE:-$default_logging_size} DATA_SIZE=${OVIRT_VOL_DATA_SIZE:-$default_data_size} +if [ -n "$OVIRT_MPATH" ]; then + #if present then setup multipath.conf with value + config_multipath_conf + while true + do + test ! `ls /dev/mapper/mpath* 2> /dev/null | wc -l` = 0 && break + done +fi + if [ -n "$OVIRT_INIT" ]; then # if present, use the drive selected with 'ovirt_init' boot parameter DRIVE=$OVIRT_INIT diff --git a/scripts/ovirt-config-uninstall b/scripts/ovirt-config-uninstall index 92ce2d0..95a71a9 100755 --- a/scripts/ovirt-config-uninstall +++ b/scripts/ovirt-config-uninstall @@ -47,6 +47,14 @@ if ask_yes_or_no "Do you wish to continue and uninstall this node ([Y]es/[N]o)?" log "Unmounting boot partition" umount $partition log "Removing partitions" + eval $(echo $partition | awk ' { + print "drive=" substr($0,1,length($1)-1); + print "drive2=" substr($0,1,length($1)-2); + }') + if [ ! -e "$drive" ]; then + # e.g. c0d0p1 + drive="$drive2" + fi drive=$(echo $partition | awk '{ print substr($0, 1, length($0) - 1) }') parted -s $drive "rm 1" parted -s $drive "rm 2" diff --git a/scripts/ovirt-early b/scripts/ovirt-early index 8990727..5632fb0 100755 --- a/scripts/ovirt-early +++ b/scripts/ovirt-early @@ -148,6 +148,7 @@ start() { # collectd=server[:port] # hostname=fqdn # TBD logrotate maxsize + # mpath format: mpath=wwid:[wwid] # BOOTIF=link|eth*|<MAC> (appended by pxelinux) # network boot interface is assumed to be on management network where @@ -236,6 +237,12 @@ start() { collectd_server collectd_port + # mpath=wwid:[wwid...] + # set a list of comma or colon separated wwids to allow + # for multipath install + # Specify ALL to use all devices + mpath+ # save boot parameters like console= for local disk boot menu bootparams cat /etc/system-release >> $OVIRT_LOGFILE @@ -286,8 +293,7 @@ start() { =/dev/*) bus serial- i=${i#=} - init=$(ls -1 "$i" 2>/dev/null | head -n1) + init=${i#=} ;; *) bus@@ -374,6 +380,10 @@ start() { console=*) bootparams="$bootparams $i" ;; + mpath=*) + i=${i#mpath=} + mpath=$(echo $i|tr ",:;" " ") + ;; esac done @@ -384,7 +394,7 @@ start() { ip_gateway=$gateway fi # save boot parameters as defaults for ovirt-config-* - params="bootif init vol_boot_size vol_swap_size vol_root_size vol_config_size vol_logging_size vol_data_size local_boot standalone overcommit ip_address ip_netmask ip_gateway ipv6 dns ntp vlan ssh_pwauth syslog_server syslog_port collectd_server collectd_port bootparams hostname firstboot" + params="bootif init vol_boot_size vol_swap_size vol_root_size vol_config_size vol_logging_size vol_data_size local_boot standalone overcommit ip_address ip_netmask ip_gateway ipv6 dns ntp vlan ssh_pwauth syslog_server syslog_port collectd_server collectd_port bootparams hostname firstboot mpath" # mount /config unless firstboot is forced if [ "$firstboot" != "1" ]; then mount_config -- 1.6.2.5