Damn, once again there are some remains from my tests... Please disregard
the file "partman-auto-lvm-multiple-disks-20080728.diff" from my previous
message. Here is the clean one.
Cheers,
Grégory
Index: debian/partman-auto-lvm.templates
===================================================================
--- debian/partman-auto-lvm.templates (révision 54599)
+++ debian/partman-auto-lvm.templates (copie de travail)
@@ -42,3 +42,19 @@
the volume group.
.
Check /var/log/syslog or see virtual console 4 for the details.
+
+Template: partman-auto-lvm/no_such_pv
+Type: error
+_Description: Inexistant PV declared
+ A Volume Group definition contains a reference to a Physical Volume
+ that is not present.
+ .
+ Check for you connectivity or the recipe.
+
+Template: partman-auto-lvm/no_pv_in_vg
+Type: error
+_Description: No PV defined for creating VG
+ The recipe contains the definition of a Volume Group without
+ any Physical Volume in it.
+ .
+ Review the recipe.
Index: lib/auto-lvm.sh
===================================================================
--- lib/auto-lvm.sh (révision 54599)
+++ lib/auto-lvm.sh (copie de travail)
@@ -10,14 +10,48 @@
exit 1
}
+# This function was copied from another file (partman-auto/lib/initial_auto).
+# Maybe it should be useful to put it in auto-shared.sh or in base.sh
+dev_to_partman () {
+ local dev_name="$1"
+ local dev
+
+ local mapped_dev_name="$(mapdevfs $dev_name)"
+ if [ -n "$mapped_dev_name" ]; then
+ dev_name="$mapped_dev_name"
+ fi
+
+ for dev in $DEVICES/*; do
+ [ -d "$dev" ] || continue
+
+ # mapdevfs both to allow for different ways to refer to the
+ # same device using devfs, and to allow user input in
+ # non-devfs form
+ if [ "$(mapdevfs $(cat $dev/device))" = "$dev_name" ]; then
+ echo $dev
+ fi
+ done
+}
+
auto_lvm_prepare() {
- local dev method size free_size normalscheme target
+ local dev method size free_size normalscheme target extra_devices tmpdev tmpdevdir physdev
dev=$1
method=$2
[ -f $dev/size ] || return 1
size=$(cat $dev/size)
+ extra_devices=''
+ if db_get partman-auto-lvm/extra_devices && [ "$RET" ]; then
+ for tmpdev in "$RET"; do
+ tmpdevdir="$(dev_to_partman $tmpdev)"
+ if [ -d "$tmpdevdir" ]; then
+ size=$(($size + $(cat $tmpdevdir/size)))
+ extra_devices="$extra_devices $tmpdevdir"
+ fi
+ done
+ fi
+
# Be sure the modules are loaded
modprobe dm-mod >/dev/null 2>&1 || true
modprobe lvm-mod >/dev/null 2>&1 || true
@@ -26,21 +60,32 @@
log-output -t update-dev update-dev
fi
- target="$(humandev $(cat $dev/device)) - $(cat $dev/model)"
+ if [ $extra_devices ]; then
+ for extradev in $dev $extra_devices; do
+ extradev_str="$extradev_str $(cat $extradev/device)"
+ done
+ target="Multiple disks ($extradev_str)"
+ else
+ target="$(humandev $(cat $dev/device)) - $(cat $dev/model)"
+ fi
target="$target: $(longint2human $size)"
free_size=$(expr 0000000"$size" : '0*\(..*\)......$') # convert to megabytes
choose_recipe lvm "$target" "$free_size" || return $?
- auto_init_disk "$dev" || return $?
+ size=0
+ for tmpdev in $dev $extra_devices; do
+ auto_init_disk "$tmpdev" || return $?
+ size=$(($size + $free_size))
- # Check if partition is usable; use existing partman-auto template as we depend on it
- if [ "$free_type" = unusable ]; then
- db_input critical partman-auto/unusable_space || true
- db_go || true
- return 1
- fi
- free_size=$(expr 0000000"$free_size" : '0*\(..*\)......$') # convert to megabytes
+ # Check if partition is usable; use existing partman-auto template as we depend on it
+ if [ "$free_type" = unusable ]; then
+ db_input critical partman-auto/unusable_space || true
+ db_go || true
+ return 1
+ fi
+ done
+ free_size=$(expr 0000000"$size" : '0*\(..*\)......$') # convert to megabytes
decode_recipe $recipe lvm
@@ -88,11 +133,6 @@
;;
esac
- # Creating envelope
- scheme="$normalscheme${NL}100 1000 1000000000 ext3 \$primary{ } method{ $method }"
-
- expand_scheme
-
clean_method
# This variable will be used to store the partitions that will be LVM
@@ -101,27 +141,70 @@
# (still one atm)
devfspv_devices=''
- create_primary_partitions
+ # Creating envelope
+ # Only if one does not already exist (identified by 'method{ lvm }' and by
+ # the current device in the scheme)
+ physdev=$(cat $dev/device)
+ if ! echo "$normalscheme" | grep -E "method\{ (lvm|crypto) \}" | grep -q "device{ $physdev[[:digit:]]* }" && \
+ ! echo "$normalscheme" | grep -E "method\{ (lvm|crypto) \}" | grep -q -v "device{"; then
+ normalscheme="$normalscheme${NL}100 1000 1000000000 ext3 \$primary{ } method{ $method }"
+ fi
- create_partitions
+ # Creating the partitions that have no device declared on the default device
+ # and partitions declared on it
+ scheme=$(echo "$normalscheme" | grep -v 'device{')
+ scheme=${scheme}${NL}$(echo "$normalscheme" | grep "device{ $physdev[[:digit:]]* }" )
+ auto_lvm_create_partitions $dev
+ # Creating the partitions declared on each of the extra devices
+ for tmpdev in $extra_devices; do
+ physdev=$(cat $tmpdev/device)
+ scheme=$(echo "$normalscheme" | grep "device{ $physdev[[:digit:]]* }" )
+ [ -n "$scheme" ] && auto_lvm_create_partitions $tmpdev
+ done
+
if ! confirm_changes partman-lvm; then
return 30
fi
+ disable_swap
# Write the partition tables
- disable_swap
- cd $dev
- open_dialog COMMIT
- close_dialog
+ for tmpdev in $dev $extra_devices; do
+ cd $tmpdev
+ open_dialog COMMIT
+ close_dialog
+ device_cleanup_partitions
+ done
- device_cleanup_partitions
update_all
}
+# This function depends on the existence of $scheme and $devfspv_devices in scope
+auto_lvm_create_partitions() {
+ local dev free_size
+ dev=$1
+
+ get_disk_infos $dev;
+ free_size=$(expr 0000000"$free_size" : '0*\(..*\)......$') # convert to megabytes
+
+ expand_scheme
+
+ create_primary_partitions
+ create_partitions
+}
+
auto_lvm_perform() {
+ local IFS physdev defvgname schemeline schemevg schemedev targetdir targetvg pvdevice
+ [ -n $1 ] || return 1
+
+ physdev=$(cat $1/device)
+ if echo $physdev | grep -q '/mapper/.*_crypt'; then
+ physdev=$(echo $physdev | sed -re 's#mapper/([^[:digit:]]+)[[:digit:]]_crypt#\1#')
+ fi
+ targetdir="/tmp/auto_lvm_perform"
+ mkdir $targetdir || exit 1
+
# Use hostname as default vg name (if available)
- local defvgname pv
db_get partman-auto-lvm/new_vg_name
if [ -z "$RET" ]; then
if [ -s /etc/hostname ]; then
@@ -150,13 +233,93 @@
db_register partman-auto-lvm/new_vg_name_exists partman-auto-lvm/new_vg_name
done
- if vg_create "$VG_name" $pv_devices; then
- perform_recipe_by_lvm $VG_name $recipe
- else
- bail_out vg_create_error
+ # The recipe contains all the necessary informations about eventuals
+ # extra VGs to create
+ # The VGs to create are :
+ # - the default one if some partitions don't have the invg{ } tag
+ # - the ones present in vgname{ } tags of PVs
+ decode_recipe $recipe lvm
+
+ # Recreating the envelope if needed
+ if ! echo "$scheme" | grep -E "method\{ (lvm|crypto) \}" | grep -q "device{ $physdev[[:digit:]]* }" && \
+ ! echo "$scheme" | grep -E "method\{ (lvm|crypto) \}" | grep -q -v "device{"; then
+ scheme="$scheme${NL}100 1000 1000000000 ext3 \$primary{ } method{ $method }"
fi
- vg_lock_pvs "$VG_name" $pv_devices
+ # Extracting the VGs to create, and on which devices
+ # Physical devices will be stored in /tmp/$VGNAME, one per line
+ IFS="$NL"
+ for schemeline in $scheme; do
+ restore_ifs
+ # Type of the line : PV or partition
+ if echo $schemeline | grep -q '\$lvmok{'; then
+ # It's a partition
+ # Check if a VG name is given
+ schemevg=$(echo $schemeline | grep 'invg{' | sed -e 's!.*invg{ *\([^ }]*\) *}.*!\1!g')
+ # If not, it will be in the default VG
+ # The file are touch()'ed to have an error generated later
+ # if they are empty
+ if [ -z "$schemevg" ]; then
+ touch $targetdir/$VG_name
+ else
+ touch $targetdir/$schemevg
+ fi
+ elif echo $schemeline | grep -v -q 'mountpoint{'; then
+ # It's a PV
+ # Check if a VG name is given
+ schemevg=$(echo $schemeline | grep -E 'method\{ (lvm|crypto) \}' | grep 'vgname{' | sed -e 's!.*vgname{ *\([^ }]*\) *}.*!\1!g')
+ # Check if a device is given
+ schemedev=$(echo $schemeline | grep -E 'method\{ (lvm|crypto) \}' | grep 'device{' | sed -e 's!.*device{ *\([^ }]*\) *}.*!\1!g')
+
+ # If no VG is given, then it will be in the default one
+ if [ -z "$schemevg" ]; then
+ tmpschemename=$VG_name
+ else
+ tmpschemename=$schemevg
+ fi
+
+ # If no physical device is given, then it is created on the default one
+ if [ -z "$schemedev" ]; then
+ tmpdevname=$physdev
+ else
+ tmpdevname=$schemedev
+ fi
+
+ # Getting the partition name from $pv_devices
+ pvdev_found=''
+ for pvdevice in $pv_devices; do
+ if echo $pvdevice | grep -q '/mapper/.*_crypt'; then
+ tmppvdev=$(echo $pvdevice | sed -re 's#mapper/([^[:digit:]]+)[[:digit:]]*_crypt#\1#')
+ tmppvdev_nocrypt=$(echo $pvdevice | sed -re 's#mapper/([^[:digit:]]+[[:digit:]]*)_crypt#\1#')
+ else
+ tmppvdev=$(echo $pvdevice | sed -re 's/[[:digit:]]+$//g')
+ fi
+ if [ $tmpdevname = $tmppvdev ] || [ $tmpdevname = $pvdevice ] || [ $tmpdevname = $tmppvdev_nocrypt ]; then
+ tmpdevname=$(mapdevfs $pvdevice)
+ pvdev_found='yes'
+ break
+ fi
+ done
+
+ if [ "$pvdev_found" = yes ]; then
+ echo $tmpdevname >> $targetdir/$tmpschemename
+ else
+ bail_out no_such_pv
+ fi
+ fi
+ done
+
+ for targetvg in $targetdir/*; do
+ pv_devices=$(cat $targetvg)
+ [ -z "$pv_devices" ] && bail_out no_pv_in_vg
+ if vg_create "$(basename $targetvg)" $pv_devices; then
+ perform_recipe_by_lvm $(basename $targetvg) $recipe
+ else
+ bail_out vg_create_error
+ fi
+ vg_lock_pvs "$VG_name" $pv_devices
+ done
+
# Default to accepting the autopartitioning
menudir_default_choice /lib/partman/choose_partition finish finish || true
}
Index: perform_recipe_by_lvm
===================================================================
--- perform_recipe_by_lvm (révision 54599)
+++ perform_recipe_by_lvm (copie de travail)
@@ -7,10 +7,18 @@
VG_name=$1
recipe=$2
+db_get partman-auto-lvm/new_vg_name
+default_vgname="$RET"
+
decode_recipe $recipe lvm
+tmpscheme=$(echo "$scheme" | grep lvmok)
+scheme=$(echo "$tmpscheme" | grep "invg{ *$VG_name *}")
+if [ $VG_name = $default_vgname ]; then
+ # Adding in the scheme the partitions that have no VG declared
+ extraschemelines=$(echo "$tmpscheme" | grep lvmok | grep -v 'invg{')
+ scheme="${scheme:+$scheme$NL}$extraschemelines"
+fi
-scheme=$(echo "$scheme" | grep lvmok)
-
partstep=$(echo "$scheme" | wc -l)
partstep=$(expr $partstep + 3)
@@ -48,8 +56,12 @@
name_number=1
foreach_partition '
- if echo $* | grep -q "mountpoint{"; then
+ if echo $* | grep -q "lvname{"; then
lvname=$(echo $* | sed \
+ -e "s/.*lvname{ *\([^ }]*\) *}.*/\1/g"
+ )
+ elif echo $* | grep -q "mountpoint{"; then
+ lvname=$(echo $* | sed \
-e "s/.*mountpoint{ *\([^ }]*\) *}.*/\1/g" \
-e "s!//!/!g" \
-e '\''s!/$!!g'\'' \
Index: autopartition-lvm
===================================================================
--- autopartition-lvm (révision 54599)
+++ autopartition-lvm (copie de travail)
@@ -13,4 +13,4 @@
pv_devices="$pv_devices $realpath"
done
-auto_lvm_perform || exit 1
+auto_lvm_perform $dev || exit 1