Hi, Here is an updated version of the patch, dealing with LVM+crypto, as suggested by Jérémy Bobbio. This patch also incorporate his modifications to add the possibility to define a custom LV name (see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=484272).
This patch have been tested in the following cases, and worked fine each time. Please note however that Grub installation failed systematically, and I had to install it by hand from the install CD. I presume it is not related to my patch, but to my lack of d-i fu when remastering the CD. Here are the tests : - with the three base recipes and method lvm ; - with the three base recipes and method crypto ; - with method lvm and the four recipes already provided, slightly modified to add "lvname{ }" at random places ; - with method crypto and the four recipes already provided, modified as per per the previous point, and replacing "method{ lvm }" by "method{ crypto }" in the PV declarations ; - with the first provided recipe, but booting without a disk used in the recipe, to test the error partman_auto_lvm/no_such_pv; It indeed failed ; - with a custom recipe containing a VG declaration without a PV associated to test the error partman_auto_lvm/no_pv_in_vg. Attached are the patches against each modified package, and the recipes modified with the "lvname{ }" attributes. Cheers, Grégory
Index: autopartition-crypto =================================================================== --- autopartition-crypto (révision 54599) +++ autopartition-crypto (copie de travail) @@ -3,10 +3,10 @@ . /lib/partman/lib/auto-lvm.sh . /lib/partman/lib/crypto-base.sh -dev="$1" +argdev="$1" method=crypto -auto_lvm_prepare $dev $method || exit 1 +auto_lvm_prepare $argdev $method || exit 1 found=no for dev in $DEVICES/*; do @@ -28,15 +28,16 @@ echo dm-crypt > $id/crypto_type crypto_prepare_method "$dev/$id" dm-crypt || exit 1 - found=yes - break +# found=yes +# break done - [ $found = yes ] && break +# [ $found = yes ] && break done crypto_check_setup || exit 1 crypto_setup no || exit 1 +pv_devices='' # This is a kludge to workaround parted's refusal to allow dm devices # to be used for LVM for dev in $DEVICES/*; do @@ -45,7 +46,7 @@ [ -f "$dev/device" ] || continue # Found it - pv_devices=$(cat $dev/device) + pv_devices="$pv_devices $(cat $dev/device)" # We should have only one partition, but lets be thorough cd $dev @@ -65,7 +66,7 @@ done done -auto_lvm_perform || exit 1 +auto_lvm_perform $argdev || exit 1 # partman likes to believe that the virtual devices have a changed # partition table
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,99 @@ 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 pvdevice in $pv_devices; do + if ! grep -q $pvdevice $targetdir/*; then + echo $pvdevice >> $targetdir/$VG_name + 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
Index: lib/auto-shared.sh =================================================================== --- lib/auto-shared.sh (révision 54599) +++ lib/auto-shared.sh (copie de travail) @@ -7,6 +7,13 @@ # Create new disk label; don't prompt for label . /lib/partman/lib/disk-label.sh create_new_label "$dev" no || return 1 + + get_disk_infos $dev +} + +get_disk_infos() { + local dev + dev="$1" cd $dev
testrecipe-01
Description: Binary data
testrecipe-02
Description: Binary data
testrecipe-03
Description: Binary data
testrecipe-04
Description: Binary data