[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[rfc patch] grub-installer - help please



Hi,

I am attempting to fix the grub-installer issues last referenced in the
thread "# d-i wheezy rc2 preparation, take 2". The current state of my
patch is shown at the end of this message. The basic idea is to add a
question which lets the user select which disk to use for installation
of the grub bootloader and show this when appropriate.

I built a modified udeb and installed it with udpkg near the end of the
installation, after tasksel was complete.

The problem I am having is that debconf is failing with an 'internal error',
error code 100 when I try to have the new question asked.
Can anyone see what I am doing wrong with the way I am asking debconf to
do things? The syslog, when I run my modified version from a terminal
in the installer (DEBCONF_DEBUG=5 sh grub-installer /target)
looks like this:

...
Apr 22 04:04:28 frontend: --> SETTITLE debian-installer/grub-installer/title
Apr 22 04:04:28 frontend: <-- 0 OK
Apr 22 04:04:28 frontend: --> GET cdrom-detect/hybrid
Apr 22 04:04:28 frontend: <-- 10 cdrom-detect/hybrid doesn't exist
Apr 22 04:04:28 frontend: --> PROGRESS STEP 1
Apr 22 04:04:28 frontend: <-- 0 OK
Apr 22 04:04:28 frontend: --> PROGRESS INFO grub-installer/progress/step_bootdev
Apr 22 04:04:28 frontend: <-- 0 OK
Apr 22 04:04:28 frontend: --> FSET grub-installer/choose_bootdev seen false
Apr 22 04:04:28 frontend: <-- 0 false
Apr 22 04:04:28 frontend: --> GET grub-installer/bootdev
Apr 22 04:04:28 frontend: <-- 0 
Apr 22 04:04:28 frontend: --> INPUT high grub-installer/only_debian
Apr 22 04:04:28 frontend: <-- 0 question will be asked
Apr 22 04:04:28 frontend: --> GO
Apr 22 04:04:31 frontend: <-- 0 ok
Apr 22 04:04:31 frontend: --> GET grub-installer/only_debian
Apr 22 04:04:31 frontend: <-- 0 true
Apr 22 04:04:31 grub-installer: Bootdev Choices: 'Enter device manually, /dev/sda, /dev/sdb'
Apr 22 04:04:31 grub-installer: Bootdev Descriptions: ', ata-FUJITSU_MHS2020AT_E_NL12T3518KU5, usb-Intel_Flash_Disk2.0_2B0B43129B5400EA-0:0'
Apr 22 04:04:31 frontend: --> SUBST grub-installer/choose_bootdev CHOICES Enter device manually, /dev/sda, /dev/sdb
Apr 22 04:04:31 frontend: Adding [CHOICES] -> [Enter device manually, /dev/sda, /dev/sdb]
Apr 22 04:04:31 frontend: <-- 0
Apr 22 04:04:31 frontend: --> SUBST grub-installer/choose_bootdev DESCRIPTIONS , ata-FUJITSU_MHS2020AT_E_NL12T3518KU5, usb-Intel_Flash_Disk2.0_2B0B43129B5400EA-0:0
Apr 22 04:04:31 frontend: Adding [DESCRIPTIONS] -> [, ata-FUJITSU_MHS2020AT_E_NL12T3518KU5, usb-Intel_Flash_Disk2.0_2B0B43129B5400EA-0:0]
Apr 22 04:04:31 frontend: <-- 0
Apr 22 04:04:31 frontend: --> INPUT high grub-installer/choose_bootdev
Apr 22 04:04:31 frontend: <-- 0 question will be asked
Apr 22 04:04:31 frontend: --> GO
Apr 22 04:04:31 frontend: <-- 100 internal error
Apr 22 04:04:31 grub-installer: Returning to menu
Apr 22 04:04:31 frontend: --> PROGRESS STOP
Apr 22 04:04:31 frontend: <-- 0 OK
Apr 22 04:04:31 frontend: Question database /var/lib/cdebconf/passwords.dat clean; not saving
Apr 22 04:04:31 frontend: Template database /var/lib/cdebconf/templates.dat clean; not saving

Kind regards
Vince

diff --git a/debian/grub-installer.templates b/debian/grub-installer.templates
index 888a656..ad840ce 100644
--- a/debian/grub-installer.templates
+++ b/debian/grub-installer.templates
@@ -86,6 +86,20 @@ _Description: Device for boot loader installation:
     drive;
   - "/dev/fd0" will install GRUB to a floppy.
 
+Template: grub-installer/choose_bootdev
+Type: select
+# :sl2:
+_Description: Select disk for boot loader installation:
+ You need to make the newly installed system bootable, by installing
+ the GRUB boot loader on a bootable device. The usual way to do this is to
+ install GRUB on the master boot record of your first hard drive. If you
+ prefer, you can install GRUB elsewhere on the drive, or to another drive,
+ or even to a floppy.
+ .
+ Select a disk from the list. GRUB will be installed to the master boot
+ record of that disk. If you want to install GRUB somewhere other than the
+ master boot record of the listed disks, select 'Enter device manually'.
+
 Template: grub-installer/password
 Type: password
 # :sl2:
diff --git a/debian/po/templates.pot b/debian/po/templates.pot
index dad01db..54085e6 100644
--- a/debian/po/templates.pot
+++ b/debian/po/templates.pot
@@ -198,6 +198,23 @@ msgid ""
 " - \"/dev/fd0\" will install GRUB to a floppy."
 msgstr ""
 
+#. Type: string
+#. Description
+#. :sl2:
+#: ../grub-installer.templates:7001
+msgid "Select disk for boot loader installation:"
+msgstr ""
+
+#. Type: string
+#. Description
+#. :sl2:
+#: ../grub-installer.templates:7001
+msgid ""
+"Select a disk from the list. GRUB will be installed to the master boot\n"
+"record of that disk. If you want to install GRUB somewhere other than the\n"
+"master boot record of the listed disks, select 'Enter device manually'.\n"
+msgstr ""
+
 #. Type: password
 #. Description
 #. :sl2:
diff --git a/grub-installer b/grub-installer
index f01eda1..151ee0f 100755
--- a/grub-installer
+++ b/grub-installer
@@ -217,6 +217,50 @@ devices_to_ids()
 	echo "$ids"
 }
 
+
+# Produce a comma-separated list of '/dev/X (id)' strings suitable for debconf.
+# The first argument will select /dev/X or (id) strings to be returned.
+# The second argument will cause that <device> to be the only one returned.
+# Examples:
+#  echo $(device_list)
+#  /dev/sda (ata-SAMSUNG_SSD_PM810_2.5__7mm_128GB_S0NRNEABC02304), /dev/sdb (ata-WDC_WD2002FAEX-007BA0_WD-WMAY05111513)
+#  echo $(device_list /dev/sdb)
+#  /dev/sdb (ata-WDC_WD2002FAEX-007BA0_WD-WMAY05111513)
+
+device_list()
+{
+        local result arg id path dev disk output
+        result="$1"
+	case "$result" in
+		/*) result="both"; arg="$1" ;;
+                *)  arg="$2" ;;
+	esac
+
+	case "$result" in
+		disk*|device*) filter_dev() { cut -d' ' -f1; }; ;;
+		description*)  filter_dev() { cut -d' ' -f2; }; ;;
+		*)             filter_dev() { cat; }; ;;
+	esac
+
+        [ -d /dev/disk/by-id ] || return
+        # /dev/disk/by-id has multiple links for the same physical disk.
+        # Sorting the output on only one column gives just one disk,path pair
+        # for each of the physical disks. Then filter out the columns we want.
+        output="$(
+                for path in /dev/disk/by-id/*; do
+                        [ -e "$path" ] || continue
+                        id="$(echo "$path" | sed -e 's+^.*/++')"
+                        dev="$(readlink -f "$path")"
+                        disk="$(device_to_disk "$dev")"
+                        [ -n "$arg" ] && dev="$arg"
+                        [ "$dev" = "$disk" ] && printf '%s %s\n' "$disk" "$id"
+                done | \
+                sort -k1,1 -s -u | filter_dev | sed -e 's/$/, /'
+        )"
+	output="$(echo $output | sed -e 's/, *$//')"
+        echo "$output"
+}
+
 rootfs=$(findfs /)
 bootfs=$(findfs /boot)
 [ -n "$bootfs" ] || bootfs="$rootfs"
@@ -590,6 +634,61 @@ esac
 db_progress STEP 1
 db_progress INFO grub-installer/progress/step_bootdev
 
+select_bootdev() {
+	local manual_entry bootdev_choices default_choice chosen result
+
+	result=""
+	default_choice="$1"
+
+	manual_entry="Enter device manually"
+	bootdev_choices="$(device_list disk)"
+	bootdev_descriptions="$(device_list description)"
+
+	bootdev_choices="$manual_entry, $bootdev_choices"
+	bootdev_descriptions=", $bootdev_descriptions"
+	log "Bootdev Choices: '$bootdev_choices'"
+	log "Bootdev Descriptions: '$bootdev_descriptions'"
+
+	# not clear if we need to do this inside this function
+	#db_fset  grub-installer/choose_bootdev seen false
+
+	db_subst grub-installer/choose_bootdev CHOICES "$bootdev_choices"
+	db_subst grub-installer/choose_bootdev DESCRIPTIONS "$bootdev_descriptions"
+	# set initial selection
+        if [ -n "$default_choice" ] ; then
+		chosen="$(device_list $default_choice)"
+		if [ -n "$chosen" ] ;then
+			db_set grub-installer/choose_bootdev "$chosen"
+		fi
+	fi
+
+	# what priority - critical, or high?
+	db_input high grub-installer/choose_bootdev || true
+	if ! db_go; then
+		log "Returning to menu"
+		db_progress STOP
+		exit 10
+	fi
+	if [ "$RET" = "$manual_entry" ] ; then
+		result=""
+	else
+		result="(echo "$RET" | cut -d' ' -f1)"
+	fi
+
+	echo "$result"
+}
+
+# make sure this question is displayed at least once
+db_fset  grub-installer/choose_bootdev seen false
+
+if [ "$bootdev" != "dummy" ] && [ ! "$frdev" ]; then
+    # check for a preseeded value
+    db_get grub-installer/bootdev || true
+    if [ -n "$RET" ] ; then
+	bootdev="$RET"
+    fi
+fi
+
 while : ; do
 	if [ "$state" = 1 ]; then
 		db_input high $q || true
@@ -600,8 +699,17 @@ while : ; do
 		fi
 		db_get $q
 		if [ "$RET" = true ]; then
-			bootdev="$default_bootdev"
-			break
+			# default_bootdev can be guessed incorrectly.
+			# If the user supplied a value for bootdev,
+			# ask them to resolve any conflict.
+			if [ "$bootdev" != "$default_bootdev" ] ; then
+				bootdev="$(select_bootdev "$bootdev")"
+			fi
+			if [ -e "$bootdev" ] ; then
+			    break
+			else
+			    state=2
+			fi
 		else
 			# Exit to menu if /boot is on SATA RAID/multipath; we
 			# don't support device selection in that case
@@ -612,7 +720,13 @@ while : ; do
 			state=2
 		fi
 	elif [ "$state" = 2 ]; then
-		db_input critical grub-installer/bootdev || true
+
+		# this won't necessarily display a question
+		bootdev="$(select_bootdev "$bootdev")"
+
+		if [ ! -e "$bootdev" ]; then
+		    db_input critical grub-installer/bootdev || true
+		fi
 		if ! db_go; then
 			if [ "$q" ]; then
 				state=1


Reply to: