[linux-lvm] [PATCH 04/35] fsadm: Make "create" command more vg aware

Lukas Czerner lczerner at redhat.com
Wed Sep 21 16:45:23 UTC 2011


Update create command so we can also specify volume group (pool) from
which we want to create logical volume, or, if neither device with
sufficient space, nor volume group is specified, it decides
automatically ho the logical volume should be created.

Also fix the list command so it will not print wrong data in case that
none was loaded.

Signed-off-by: Lukas Czerner <lczerner at redhat.com>
---
 scripts/fsadm.sh |  207 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 167 insertions(+), 40 deletions(-)

diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
index 803c6a5..00b5019 100755
--- a/scripts/fsadm.sh
+++ b/scripts/fsadm.sh
@@ -76,6 +76,9 @@ BLOCKCOUNT=
 MOUNTPOINT=
 MOUNTED=
 REMOUNT=
+IN_GROUP=
+NOT_IN_GROUP=
+GROUP=
 PROCMOUNTS="/proc/mounts"
 PROCDEVICES="/proc/devices"
 PROCPARTITIONS="/proc/partitions"
@@ -134,6 +137,14 @@ dry() {
 	fi
 }
 
+float_math() {
+	if [ $# -le 0 ]; then
+		return
+	fi
+	result=$(LANG=C echo "scale=2; $@" | $BC -q 2> /dev/null)
+	echo $result
+}
+
 is_natural() {
 	test "$1" -ge 0 &> /dev/null && return 1
 	return 0
@@ -204,9 +215,10 @@ detect_fs() {
 	esac
 	# use null device as cache file to be sure about the result
 	# not using option '-o value' to be compatible with older version of blkid
-	FSTYPE=$("$BLKID" -c "$NULL" -s TYPE "$VOLUME") || error "Cannot get FSTYPE of \"$VOLUME\""
+	FSTYPE=$("$BLKID" -c "$NULL" -s TYPE "$VOLUME") || return 1
 	FSTYPE=${FSTYPE##*TYPE=\"} # cut quotation marks
 	FSTYPE=${FSTYPE%%\"*}
+	return 0
 }
 
 # check if the given device is already mounted and where
@@ -417,6 +429,7 @@ generic_make_fs() {
 resize() {
 	NEWSIZE=$2
 	detect_fs "$1"
+	[ $? -eq 1 ] && error "Cannot get FSTYPE of \"$VOLUME\""
 	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
 	is_natural $NEWSIZE
 	[ $? -ne 1 ] && error "$NEWSIZE is not valid number for file system size"
@@ -438,19 +451,52 @@ resize() {
 name_exists() {
 	cmd=$1
 	search=$2
-	$LVM $cmd --separator ' ' 2>&1 | tail -n-1 | cut -d' ' -f3 | grep $search 2>&1> /dev/null
+	$LVM $cmd --separator ' ' --noheadings --nosuffix 2>&1 | cut -d' ' -f3 | grep $search 2>&1> /dev/null
 	if [ $? -eq 0 ]; then
 		return 1
 	fi
 	return 0
 }
 
+detect_device_group() {
+	devices=$@
+	ret=0
+	prev_vgname=""
+	vgs=""
+
+	NOT_IN_GROUP=
+	IN_GROUP=
+	for i in $devices; do
+		cur_vgname=$(LANG=C $LVM pvs -o vg_name --separator ' ' --noheadings --nosuffix --units k $i 2> /dev/null | sed -e 's/^ *//')
+
+		if [ -z $cur_vgname ]; then
+			NOT_IN_GROUP+="$i "
+			continue
+		else
+			IN_GROUP+="$i "
+		fi
+
+		if [ -z $prev_vgname ]; then
+			prev_vgname=$cur_vgname
+			vgs=$cur_vgname
+			continue;
+		fi
+
+		if [ "$cur_vgname" != "$prev_vgname" ]; then
+			ret=1
+			vgs+=" $cur_vgname"
+		fi
+	done
+	GROUP=$vgs
+	return $ret
+}
+
 #############################
 # Create a new logical volume
 #############################
 create() {
-	size="-l 100%FREE"
 	devcount=0
+	vg_create=0
 
 	for i in $@; do
 		if [ -b $i ]; then
@@ -460,23 +506,76 @@ create() {
 		fi
 		case $i in
 			"stripesize"* | "chunksize"*) stripesize=${i##*=} ;;
-			"name"*) name="--name ${i##*=}" ;;
+			"name"*) name=${i##*=} ;;
 			"fstyp"* | "fs"*) fstyp=${i##*=} ;;
-			"size"*) size="-L ${i##*=}" ;;
-			*) error "Wrong option $i. (see: $TOOL --help)"
+			"size"*) size=${i##*=} ;;
+			*) if [ -z $vg ]; then vgname=$i; else
+				error "Wrong option $i. (see: $TOOL --help)"
+			   fi ;;
 		esac
 	done
 
-	for i in $(seq -w $MAX_VGS); do
-		name_exists vgs vg${i}
-		if [ $? -eq 0 ]; then
-			vgname="vg${i}"
-			break;
+	detect_device_group $devices
+	if [ $? -ne 0 ]; then
+		error "Some of the devices are in different groups. Please run \
+			\"$TOOL list\" to get more information on layout."
+	fi
+	if [ $GROUP ] && [ $vgname ];then
+		if [ "$vgname" != "$GROUP" ]; then
+			error "You specified group ($vgname) and devices which does "\
+				"belong to a different group ($GROUP). Either remove "\
+				"devices first, or specify devices which are free."
 		fi
-	done
+	elif [ $GROUP ]; then
+		vgname=$GROUP
+	fi
+	echo $vgname
+
+	# Devices are not in any group so we should find some.
+	# Either create a new one, or use the existing one, if
+	# there is only one vgroup, or use the one with enough
+	# in it
+	if [ -z "$vgname" ]; then
+		vgroups=$($LVM vgs -o vg_name,vg_free --separator ' ' --noheadings --units b 2> /dev/null)
+		lines=$($LVM vgs -o vg_name,vg_free --separator ' ' --noheadings --units b 2> /dev/null | wc -l)
+		echo "lines = $lines"
+
+		if [ $lines -eq 1 ]; then
+			vgname=$(echo $vgroups | sed -e 's/^ *//' | cut -d' ' -f1)
+		elif [ $lines -gt 1 ]; then
+			if [ -z $size ]; then
+				error "Not enough information to create" \
+					"logical volume"
+			fi
+			decode_size $size 1
+			new_size=$NEWBLOCKCOUNT
+			IFS=$NL
+			for i in $vgroups; do
+				vgsize=$(echo $i | sed -e 's/^ *//' | cut -d' ' -f2)
+				vgsize=${vgsize%%B}
+				if [ $vgsize -ge $new_size ]; then
+					echo "Yes"
+					vgname=$(echo $i | sed -e 's/^ *//' | cut -d' ' -f1)
+					break;
+				fi
+			done
+		fi
+	fi
+	IFS=$IFS_OLD
+
+	if [ -z "$vgname" ]; then
+		[ $devcount -eq 0 ] && error "No suitable device specified."
+		for i in $(seq -w $MAX_VGS); do
+			$LVM vgs vg${i} &> /dev/null
+			if [ $? -ne 0 ]; then
+				vgname="vg${i}"
+				break;
+			fi
+		done
+		vg_create=1
+	fi
 
 	[ -z "$vgname" ] && error "No suitable name for volume group found."
-	[ $devcount -eq 0 ] && error "No suitable device specified."
 
 	if [ "$stripesize" ]; then
 		striped="-i $devcount -I $stripesize"
@@ -486,17 +585,30 @@ create() {
 		lvname="--name $name"
 	else
 		for i in $(seq -w $MAX_VGS); do
-			name_exists "vgs $vgname" lvol${i}
-			if [ $? -eq 0 ]; then
+			$LVM lvs $vgname --separator ' ' --noheadings | grep -e " lvol${i} " &> /dev/null
+			if [ $? -ne 0 ]; then
 				name="lvol${i}"
 				lvname="--name $name"
 				break;
 			fi
 		done
 	fi
+	echo "going to create logical volume $lvname"
+
+	[ -z "$lvname" ] && error "No suitable name for the logical volume."
+
+	if [ $vg_create -eq 1 ]; then
+		dry $LVM vgcreate $VERB $vgname $devices
+	elif [ ! -z $NOT_IN_GROUP ]; then
+		dry $LVM vgextend $VERB $vgname $NOT_IN_GROUP
+	fi
 
-	dry $LVM vgcreate $VERB $vgname $devices
-	dry $LVM lvcreate $VERB $lvname $size $striped $vgname
+	if [ -z $size ]; then
+		size="-l 100%FREE"
+	else
+		size="-L $size"
+	fi
+	dry $LVM lvcreate $VERB $lvname $size $striped $vgname $devices
 	device="/dev/${vgname}/${name}"
 
 	guess=0
@@ -554,7 +666,7 @@ destroy() {
 	fi
 
 	if [ -z $device ]; then
-		$LVM vgs $1
+		$LVM vgs $1 &> /dev/null
 		# Volume group has been given
 		if [ $? -eq 0 ]; then
 			dry $LVM vgremove $FORCE $1
@@ -570,14 +682,6 @@ destroy() {
 	dry $LVM lvremove $FORCE $device
 }
 
-float_math() {
-	if [ $# -le 0 ]; then
-		return
-	fi
-	result=$(LANG=C echo "scale=2; $@" | $BC -q 2> /dev/null)
-	echo $result
-}
-
 #####################################
 # Convet the size into human readable
 # form. size in KiB expected
@@ -621,7 +725,7 @@ get_ext_size() {
 	USED=$(humanize_size $used)
 	free=$((($fbcount-$rbcount)*$bsize))
 	FREE=$(humanize_size $free)
-	IFS=$OLD_IFS
+	IFS=$IFS_OLD
 }
 
 get_xfs_size() {
@@ -649,7 +753,6 @@ get_xfs_size() {
 		FREE=$(humanize_size $free)
 		return
 	fi
-
 	line=$($DF -k $VOLUME | grep -e "$MOUNTED$" | sed -e 's/  */ /g')
 	line=${line#* }
 	total=$(echo $line | cut -d' ' -f1)
@@ -658,15 +761,19 @@ get_xfs_size() {
 	FREE=$(humanize_size $free)
 	used=$(echo $line | cut -d' ' -f2)
 	USED=$(humanize_size $used)
-	IFS=$OLD_IFS
+	IFS=$IFS_OLD
 }
 
 detect_fs_size() {
+	if [ -z $FSTYPE ]; then
+		return
+	fi
 	case $FSTYPE in
 		ext[234]) get_ext_size ;;
 		xfs) get_xfs_size ;;
-		*) error "Filesystem $FSTYM is not supported by $TOOL"
+		*) return 1 ;;
 	esac
+	return 0
 }
 
 list_filesystems() {
@@ -680,22 +787,31 @@ list_filesystems() {
 	echo $separator
 	echo $header
 	echo $separator
-	IFS=$NL
 	c=0
-	for line in $($LVM lvs -o lv_path,lv_size --noheadings --separator ' ' --nosuffix --units k 2> /dev/null); do
+	for line in $(LANG=C $LVM lvs -o lv_path,lv_size --noheadings --separator ' ' --nosuffix --units k 2> /dev/null); do
 		line=$(echo $line | sed -e 's/^ *\//\//')
 		volume=$(echo $line | cut -d' ' -f1)
 		detect_fs $volume
 		detect_mounted
 		detect_fs_size
-		printf $format $volume $FSTYPE $FREE $USED $TOTAL $MOUNTED
+		if [ -z "$TOTAL" ]; then
+			total=$(echo $line | cut -d' ' -f2)
+			TOTAL=$(humanize_size ${total%%.})
+		fi
+		printf "$format" "$volume" "$FSTYPE" "$FREE" "$USED" "$TOTAL" "$MOUNTED"
+		volume=
+		FSTYPE=
+		FREE=
+		USED=
+		TOTAL=
+		MOUNTED=
 		c=$((c+1))
 	done
 	if [ $c -eq 0 ]; then
 		echo " No file systems suitable for managing by $TOOL found."
 	fi
 	echo $separator
-	IFS=$OLD_IFS
+	IFS=$IFS_OLD
 }
 
 list_devices() {
@@ -722,14 +838,19 @@ list_devices() {
 		used=$(echo $line | cut -d' ' -f5)
 		used=$(humanize_size ${used%%.*})
 
-		printf $format $device $free $used $total $group
+		printf "$format" "$device" "$free" "$used" "$total" "$group"
+		device=
+		free=
+		used=
+		total=
+		group=
 		c=$((c+1))
 	done
 	if [ $c -eq 0 ]; then
 		echo " No devices found in the pool."
 	fi
 	echo $separator
-	IFS=$OLD_IFS
+	IFS=$IFS_OLD
 }
 
 list_pool() {
@@ -745,25 +866,30 @@ list_pool() {
 	echo $header
 	echo $separator
 	c=0
-	for line in $(LANG=C $LVM vgs -o vg_name,pv_count,vg_size,vg_free --separator ' ' --noheadings --nosuffix --units k); do
+	for line in $(LANG=C $LVM vgs -o vg_name,pv_count,vg_size,vg_free --separator ' ' --noheadings --nosuffix --units k 2> /dev/null); do
 		line=$(echo $line | sed -e 's/^ *//')
 		group=$(echo $line | cut -d' ' -f1)
 		devices=$(echo $line | cut -d' ' -f2)
 		total=$(echo $line | cut -d' ' -f3)
 		free=$(echo $line | cut -d' ' -f4)
-
 		used=$((${total%%.*}-${free%%.*}))
 		used=$(humanize_size ${used%%.*})
 		total=$(humanize_size ${total%%.*})
 		free=$(humanize_size ${free%%.*})
-		printf $format $group $devices $total $free $used
+
+		printf "$format" "$group" "$devices" "$free" "$used" "$total"
+		group=
+		devices=
+		total=
+		free=
+		used=
 		c=$((c+1))
 	done
 	if [ $c -eq 0 ]; then
 		echo " Pool is empty."
 	fi
 	echo $separator
-	IFS=$OLD_IFS
+	IFS=$IFS_OLD
 }
 
 #############################
@@ -804,6 +930,7 @@ diff_dates() {
 ###################
 check() {
 	detect_fs "$1"
+	[ $? -eq 1 ] && error "Cannot get FSTYPE of \"$VOLUME\""
 	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
 	if detect_mounted ; then
 		verbose "Skipping filesystem check for device \"$VOLUME\" as the filesystem is mounted on $MOUNTED";
-- 
1.7.4.4




More information about the linux-lvm mailing list