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

Re: partman-md/mdcfg merge



I broke RAID0 creation due to a typo (log_output vs. log-output).
Version 3 attached.

-- 
Colin Watson                                       [cjwatson@ubuntu.com]
=== modified file 'choose_partition/md/choices'
--- choose_partition/md/choices	2007-12-28 16:24:47 +0000
+++ choose_partition/md/choices	2009-07-13 21:43:11 +0000
@@ -1,7 +1,5 @@
 #!/bin/sh
 
-[ -x /bin/mdcfg ] || exit 0
-
 . /lib/partman/lib/base.sh
 
 use_raid=no

=== modified file 'choose_partition/md/do_option'
--- choose_partition/md/do_option	2007-12-28 16:24:47 +0000
+++ choose_partition/md/do_option	2009-07-14 11:43:48 +0000
@@ -1,14 +1,292 @@
 #!/bin/sh
 
-. /lib/partman/lib/base.sh
+. /lib/partman/lib/md-base.sh
 . /lib/partman/lib/commit.sh
 
-confirm_changes partman-md || exit 0
+do_initial_setup () {
+	# Make sure that MD support is available
+	if [ ! -e /proc/mdstat ]; then
+		db_input critical partman-md/nomd
+		db_go
+		exit 0
+	fi
 
-commit_changes partman-md/commit_failed || exit $?
+	# Commit the changes
+	confirm_changes partman-md || exit 0
+	commit_changes partman-md/commit_failed || exit $?
 
-stop_parted_server
+	# Try to detect MD devices, and start them
+	mkdir -p /dev/md
+	log-output -t partman-md --pass-stdout \
+		mdadm --examine --scan --config=partitions >/tmp/mdadm.conf
+	log-output -t partman-md \
+		mdadm --assemble --scan --run \
+			--config=/tmp/mdadm.conf --auto=yes
+}
+
+prune_partitions () {
+	local chosen="$1"
+	local new_partitions=
+	local i j
+	for i in $PARTITIONS; do
+		local found=0
+		for j in $chosen; do
+			if [ "$i" = "$j" ]; then
+				found=1
+				break
+			fi
+		done
+		if [ "$found" -eq 0 ]; then
+			new_partitions="${new_partitions:+$new_partitions }$i"
+		fi
+	done
+	PARTITIONS="$new_partitions"
+}
+
+md_create_raid0 () {
+	db_subst partman-md/raid0devs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+	db_set partman-md/raid0devs ''
+	db_input critical partman-md/raid0devs
+	db_go || return
+
+	db_get partman-md/raid0devs
+	RET="$(csv_to_ssv "$RET")"
+	local selected="$(echo "$RET" | wc -w)"
+	prune_partitions "$RET"
+
+	local md_num="$(md_next_device_number)"
+
+	logger -t partman-md "Number of devices in the RAID0 array md$md_num: $selected"
+
+	local raid_devices="$(csv_to_ssv "$RET")"
+	log-output -t partman-md \
+		mdadm --create /dev/md$md_num --auto=yes --force -R -l raid0 \
+		      -n $selected $raid_devices || return $?
+	md_lock_devices "md$md_num" $raid_devices
+}
+
+md_create_array () {
+	local min_size i
+
+	case $1 in
+	    RAID1)	min_size=2 ;;
+	    RAID5)	min_size=3 ;;
+	    RAID6)	min_size=4 ;;
+	    RAID10)	min_size=2 ;;
+	    *)		return ;;
+	esac
+
+	local level="${1#RAID}"
+
+	for i in devcount devs sparecount sparedevs; do
+		db_subst partman-md/raid$i LEVEL "$level"
+	done
+	db_subst partman-md/raiddevcount MINIMUM "$min_size"
+
+	db_set partman-md/raiddevcount "$min_size"
+	md_db_get_number partman-md/raiddevcount "$min_size" 99 || return
+	local dev_count="$RET"
+
+	db_set partman-md/raidsparecount 0
+	md_db_get_number partman-md/raidsparecount 0 99 || return
+	local spare_count="$RET"
+
+	if [ "$level" -ne 1 ] && [ "$dev_count" -lt "$min_size" ]; then
+		# minimum number for the selected RAID level
+		dev_count="$min_size"
+	fi
+	local required="$(($dev_count + $spare_count))"
+	if [ "$level" -ne 1 ] && [ "$required" -gt "$NUM_PART" ]; then
+		db_subst partman-md/notenoughparts NUM_PART "$NUM_PART"
+		db_subst partman-md/notenoughparts REQUIRED "$required"
+		db_input critical partman-md/notenoughparts
+		db_go
+		return
+	fi
+
+	db_set partman-md/raiddevs ''
+	local selected=0
+
+	# RAID 5/6/10: loop until correct number of active devices selected
+	# RAID 1: loop until at least one device selected
+	until ([ "$level" -ne 1 ] && [ "$selected" -eq "$dev_count" ]) || \
+	      ([ "$level" -eq 1 ] && [ "$selected" -gt 0 ] && [ "$selected" -le "$dev_count" ]); do
+		db_subst partman-md/raiddevs COUNT "$dev_count"
+		db_subst partman-md/raiddevs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+		db_input critical partman-md/raiddevs
+		db_go || return
+
+		db_get partman-md/raiddevs
+		selected="$(echo "$RET" | wc -w)"
+	done
+
+	local missing_devices=
+	if [ "$level" -eq 1 ]; then
+		# Add "missing" for as many devices as weren't selected
+		while [ "$selected" -lt "$dev_count" ]; do
+			missing_devices="$missing_devices missing"
+			selected="$(($selected + 1))"
+		done
+	fi
+
+	# Remove partitions selected in raiddevs from the PARTITIONS list
+	db_get partman-md/raiddevs
+	prune_partitions "$(csv_to_ssv "$RET")"
+
+	db_set partman-md/raidsparedevs ''
+	selected=0
+	if [ "$spare_count" -gt 0 ] && [ -n "$PARTITIONS" ]; then
+		local first=1
+		# Loop until the correct number of devices has been selected.
+		# That means any number less than or equal to the spare count.
+		while [ "$selected" -gt "$spare_count" ] || [ "$first" -eq 1 ]; do
+			first=0
+			db_subst partman-md/raidsparedevs COUNT "$spare_count"
+			db_subst partman-md/raidsparedevs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+			db_input critical partman-md/raidsparedevs
+			db_go || return
 
-mdcfg
+			db_get partman-md/raidsparedevs
+			selected="$(echo "$RET" | wc -w)"
+		done
+	fi
+
+	local layout=
+	if [ "$level" -eq 10 ]; then
+		db_set partman-md/raid10layout n2
+		while :; do
+			db_input low partman-md/raid10layout
+			db_go || return
+			db_get partman-md/raid10layout
+			if echo "$RET" | egrep -q '^[nfo][0-9]{1,2}$' && \
+			   [ "$(echo "$RET" | sed 's/.//')" -le "$dev_count" ]; then
+				break
+			fi
+		done
+		layout="--layout=$RET"
+	fi
+
+	# The number of spares the user has selected
+	local named_spares="$selected"
+
+	db_get partman-md/raiddevs
+	local raid_devices="$(csv_to_ssv "$RET")"
+
+	db_get partman-md/raidsparedevs
+	local spare_devices="$(csv_to_ssv "$RET")"
+
+	local missing_spares=
+	local count="$named_spares"
+	while [ "$count" -lt "$spare_count" ]; do
+		missing_spares="$missing_spares missing"
+		count="$(($count + 1))"
+	done
+
+	local md_num="$(md_next_device_number)"
+
+	logger -t partman-md "Selected spare count: $named_spares"
+	logger -t partman-md "RAID devices count: $dev_count"
+	logger -t partman-md "Spare devices count: $spare_count"
+	log-output -t partman-md \
+		mdadm --create /dev/md$md_num --auto=yes --force -R \
+			-l raid$level $layout \
+			-n $dev_count -x $spare_count $raid_devices \
+			$missing_devices $spare_devices $missing_spares || \
+		return $?
+	md_lock_devices "md$md_num" $raid_devices $spare_devices
+}
+
+do_create () {
+	db_input critical partman-md/createmain
+	db_go || return
+	db_get partman-md/createmain
+	local raid_sel="$RET"
+	PARTITIONS="$(md_get_partitions)"
+	if [ -z "$PARTITIONS" ]; then
+		db_input critical partman-md/noparts
+		db_go
+		return
+	fi
+	NUM_PART="$(echo "$PARTITIONS" | wc -w)"
+	case $raid_sel in
+	    RAID10|RAID6|RAID5|RAID1)
+		md_create_array "$raid_sel" ;;
+	    RAID0)
+		md_create_raid0 ;;
+	esac
+}
+
+md_delete_verify () {
+	local device="$(echo "$1" | sed 's/^\(md.*\)_.*/\1/')"
+	local devices="$(grep "^$DEVICE[ :]" /proc/mdstat | \
+			 sed 's/^.*active \(.*\)/\1/; s/raid[0-9]* //')"
+	local mddev="$(md_devnode "$device")" || return 1
+	local mdtype="$(md_get_level "$mddev")"
+
+	db_set partman-md/deleteverify false
+	db_subst partman-md/deleteverify DEVICE "/dev/$device"
+	db_subst partman-md/deleteverify TYPE "$mdtype"
+	db_subst partman-md/deleteverify DEVICES "$devices"
+	db_input critical partman-md/deleteverify
+	db_go || return 0
+	db_get partman-md/deleteverify
+	[ "$RET" = true ] || return 0
+
+	# Stop the MD device and zero the superblock of all the component
+	# devices
+	devices="$(mdadm -Q --detail "$mddev" | \
+		   egrep '^[[:space:]]*[0-9].*(active|spare)' | \
+		   sed 's/.* //')"
+	logger -t partman-md "Removing $mddev ($devices)"
+	log-output -t partman-md mdadm --stop "$mddev" || return 1
+	local dev
+	for dev in $devices; do
+		log-output -t partman-md \
+			mdadm --zero-superblock --force "$dev" || return 1
+	done
+	return 0
+}
+
+do_delete () {
+	md_get_devices
+	if [ -z "$MD_DEVICES" ]; then
+		db_input high partman-md/delete_no_md
+		db_go
+		return
+	fi
+
+	db_subst partman-md/deletemenu DEVICES "$MD_DEVICES"
+	db_input critical partman-md/deletemenu
+	db_go || return
+	db_get partman-md/deletemenu
+
+	if ! md_delete_verify "$RET"; then
+		db_input critical partman-md/deletefailed
+		db_go
+	fi
+}
+
+do_initial_setup
+
+while :; do
+	db_input critical partman-md/mainmenu
+	db_go || exit 10
+	db_get partman-md/mainmenu
+	case $RET in
+	    create)	do_create ;;
+	    delete)	do_delete ;;
+	    finish)	break ;;
+	    *)
+		logger -t partman-md "Unknown selection '$RET'"
+		break ;;
+	esac
+done
+
+# Force mdadm to be installed on the target system
+apt-install mdadm
+
+stop_parted_server
 
 restart_partman
+
+exit 0

=== modified file 'debian/changelog'
--- debian/changelog	2009-06-13 06:49:21 +0000
+++ debian/changelog	2009-07-09 20:00:43 +0000
@@ -1,3 +1,12 @@
+partman-md (46) UNRELEASED; urgency=low
+
+  * Merge mdcfg, making partman-md stand-alone. Bugs fixed along the way:
+    - Talks about "software RAID" or "multiple device" rather than
+      "multidisk" (closes: #387696).
+    - Uses partman locking mechanism (closes: #499285).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 09 Jul 2009 18:23:25 +0100
+
 partman-md (45) unstable; urgency=low
 
   [ Colin Watson ]

=== modified file 'debian/control'
--- debian/control	2008-07-31 00:17:08 +0000
+++ debian/control	2009-07-09 15:36:52 +0000
@@ -9,5 +9,5 @@ Vcs-Svn: svn://svn.debian.org/d-i/trunk/
 Package: partman-md
 XC-Package-Type: udeb
 Architecture: all
-Depends: ${misc:Depends}, mdadm-udeb, mdcfg-utils, partman-base (>= 124)
+Depends: ${misc:Depends}, di-utils (>= 1.16), md-modules, mdadm-udeb (>= 2.5.2), partman-base (>= 124)
 Description: Add to partman support for MD

=== modified file 'debian/partman-md.templates'
--- debian/partman-md.templates	2008-07-31 00:18:50 +0000
+++ debian/partman-md.templates	2009-07-09 20:58:27 +0000
@@ -8,6 +8,165 @@ Type: text
 # :sl3:
 _Description: Configure software RAID
 
+Template: partman-md/text/in_use
+Type: text
+# :sl3:
+# What is "in use" is a partition
+_Description: In use by software RAID device ${DEVICE}
+
+Template: partman-md/nomd
+Type: error
+# :sl3:
+_Description: Software RAID not available
+ The current kernel doesn't seem to support software RAID (MD) devices. This
+ should be solved by loading the necessary modules.
+
+Template: partman-md/mainmenu
+Type: select
+Choices-C: create, delete, finish
+# Note to translators : Please keep your translations of the choices
+# below a 65 columns limit (which means 65 characters
+# in single-byte languages)
+# :sl3:
+__Choices: Create MD device, Delete MD device, Finish
+# :sl3:
+_Description: Software RAID configuration actions
+ This is the software RAID (or MD, "multiple device") configuration menu.
+ .
+ Please select one of the proposed actions to configure software RAID.
+
+Template: partman-md/createmain
+Type: select
+Choices: RAID0, RAID1, RAID5, RAID6, RAID10
+# :sl3:
+_Description: Software RAID device type:
+ Please choose the type of the software RAID device to be created.
+
+Template: partman-md/noparts
+Type: error
+# :sl3:
+_Description: No RAID partitions available
+ No unused partitions of the type "Linux RAID Autodetect" are available.
+ Please create such a partition, or delete an already used software RAID
+ device to free its partitions.
+ .
+ If you have such partitions, they might contain actual file systems, and
+ are therefore not available for use by this configuration utility.
+
+Template: partman-md/raid0devs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Active devices for the RAID0 array:
+ You have chosen to create a RAID0 array. Please choose the active devices
+ in this array.
+
+Template: partman-md/raiddevcount
+Type: string
+# :sl3:
+_Description: Number of active devices for the RAID${LEVEL} array:
+ The RAID${LEVEL} array will consist of both active and spare devices. The
+ active devices are those used, while the spare devices will only be used if
+ one or more of the active devices fail. A minimum of ${MINIMUM} active
+ devices is required.
+ .
+ NOTE: this setting cannot be changed later.
+
+Template: partman-md/raiddevs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Active devices for the RAID${LEVEL} array:
+ You have chosen to create a RAID${LEVEL} array with ${COUNT} active devices.
+ .
+ Please choose which partitions are active devices.
+ You must select exactly ${COUNT} partitions.
+
+Template: partman-md/raidsparecount
+Type: string
+# :sl3:
+_Description: Number of spare devices for the RAID${LEVEL} array:
+
+Template: partman-md/raidsparedevs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Spare devices for the RAID${LEVEL} array:
+ You have chosen to create a RAID${LEVEL} array with ${COUNT} spare devices.
+ .
+ Please choose which partitions will be used as spare devices.
+ You may choose up to ${COUNT} partitions. If you choose less than ${COUNT}
+ devices, the remaining partitions will be added to the array as "missing".
+ You will be able to add them to the array later.
+
+Template: partman-md/notenoughparts
+Type: error
+# :sl3:
+_Description: Not enough RAID partitions available
+ There are not enough RAID partitions available for your selected
+ configuration.  You have ${NUM_PART} RAID partitions available but
+ your configuration requires ${REQUIRED} partitions.
+
+Template: partman-md/raid10layout
+Type: string
+# :sl3:
+_Description: Layout of the RAID10 array:
+ The layout must be n, o, or f (arrangement of the copies) followed
+ by a number (number of copies of each chunk). The number must be
+ smaller or equal to the number of active devices.
+ .
+ The letter is the arrangement of the copies:
+  n - near copies: Multiple copies of one data block are at similar
+      offsets in different devices.
+  f - far copies: Multiple copies have very different offsets
+  o - offset copies: Rather than the chunks being duplicated within a
+      stripe, whole stripes are duplicated but are rotated by one
+      device so duplicate blocks are on different devices.
+ .
+ NOTE: this setting cannot be changed later.
+
+Template: partman-md/deletemenu
+Type: select
+Choices: ${DEVICES}
+# :sl3:
+_Description: Software RAID device to be deleted:
+ Deleting a software RAID device will stop it and clear the superblock of
+ all its components.
+ .
+ Please note this will not immediately allow you to reuse the partitions or
+ devices in a new software RAID device. The array will however be unusable
+ after the deletion.
+ .
+ If you select a device for deletion, you will get some information about it
+ and you will be given the option of aborting this operation.
+
+Template: partman-md/delete_no_md
+Type: error
+# :sl3:
+_Description: No software RAID devices available
+ No software RAID devices are available for deletion.
+
+Template: partman-md/deleteverify
+Type: boolean
+Default: false
+# :sl3:
+#flag:translate!:4
+_Description: Really delete this software RAID device?
+ Please confirm whether you really want to delete the following software
+ RAID device:
+ .
+  Device:            ${DEVICE}
+  Type:              ${TYPE}
+  Component devices:
+ .
+ ${DEVICES}
+
+Template: partman-md/deletefailed
+Type: error
+# :sl3:
+_Description: Failed to delete the software RAID device
+ There was an error deleting the software RAID device. It may be in use.
+
 Template: partman-md/confirm
 Type: boolean
 Default: false

=== modified file 'debian/rules'
--- debian/rules	2008-07-31 00:18:50 +0000
+++ debian/rules	2009-07-09 15:39:30 +0000
@@ -25,6 +25,7 @@ install: build
 	debian/install-rc init.d
 	debian/install-rc update.d
 	dh_install lib lib/partman
+	dh_install finish-install.d usr/lib
 
 binary-indep: build install
 	dh_testdir

=== added directory 'finish-install.d'
=== added file 'finish-install.d/65partman-md'
--- finish-install.d/65partman-md	1970-01-01 00:00:00 +0000
+++ finish-install.d/65partman-md	2009-07-09 22:00:32 +0000
@@ -0,0 +1,11 @@
+#!/bin/sh
+CF=/target/etc/mdadm/mdadm.conf
+if [ ! -s "$CF" ] && [ -e /proc/mdstat ] && \
+   grep ^md /proc/mdstat >/dev/null; then
+	mkdir -p /target/etc/mdadm
+	echo "# Autogenerated by partman-md. See mdadm.conf(5) for more details on this file." > /etc/mdadm.conf
+	echo "DEVICE partitions" >> $CF
+	chroot /target mount /proc
+	chroot /target mdadm --detail --scan >> $CF
+	chroot /target umount /proc
+fi

=== added file 'lib/md-base.sh'
--- lib/md-base.sh	1970-01-01 00:00:00 +0000
+++ lib/md-base.sh	2009-07-09 21:39:19 +0000
@@ -0,0 +1,118 @@
+. /lib/partman/lib/base.sh
+
+# Translate device from /proc/mdstat (mdX) to device node
+md_devnode () {
+	local num=$(echo $1 | sed -e "s/^md//")
+
+	# Also handle the case where the first does not exist
+	if [ -b /dev/md/$num ]; then
+		echo /dev/md/$num
+	elif [ -b /dev/md$num ]; then
+		echo /dev/md$num
+	else
+		return 1
+	fi
+}
+
+md_get_level () {
+	echo $(mdadm -Q --detail $1 | grep "Raid Level" | sed "s/.*: //")
+}
+
+md_get_devices () {
+	local device
+	MD_DEVICES=""
+	for device in $(grep ^md /proc/mdstat | \
+			sed -e 's/^\(md.*\) : .*/\1/'); do
+		local mddev=$(md_devnode $device) || return 1
+		local mdtype=$(md_get_level $mddev)
+		MD_DEVICES="${MD_DEVICES:+$MD_DEVICES, }${device}_$mdtype"
+	done
+}
+
+md_get_partitions () {
+	local dev method
+
+        PARTITIONS=""
+
+	for dev in $DEVICES/*; do
+		[ -d "$dev" ] || continue
+		cd $dev
+		open_dialog PARTITIONS
+		while { read_line num id size type fs path name; [ "$id" ]; }; do
+			[ -f $id/method ] || continue
+			method=$(cat $id/method)
+			if [ "$method" = raid ]; then
+				local mappedpath="$(mapdevfs "$path")"
+				# Exclude partitions that are already part
+				# of a RAID set
+				if ! egrep -q "(${path#/dev/}|${mappedpath#/dev/})" /proc/mdstat; then
+					echo "$mappedpath"
+				fi
+			fi
+		done
+		close_dialog
+	done
+}
+
+# Converts a list of space (or newline) separated values to comma separated values
+# TODO: duplication from partman-lvm
+ssv_to_csv () {
+	local csv value
+
+	csv=""
+	for value in $1; do
+		if [ -z "$csv" ]; then
+			csv="$value"
+		else
+			csv="$csv, $value"
+		fi
+	done
+	echo "$csv"
+}
+
+# Converts a list of comma separated values to space separated values
+# TODO: duplication from partman-lvm
+csv_to_ssv () {
+	echo "$1" | sed -e 's/ *, */ /g'
+}
+
+md_db_get_number () {
+	local question="$1"
+	local min="$2"
+	local max="$3"
+	while :; do
+		db_input critical "$question"
+		db_go || return $?
+		db_get "$question"
+		# Figure out if the user entered a number
+		RET="$(echo "$RET" | sed 's/[[:space:]]//g')"
+		if [ "$RET" ] && [ "$RET" -ge "$min" ] && [ "$RET" -le "$max" ]; then
+			break
+		fi
+	done
+	return 0
+}
+
+# Find the next available MD device number
+md_next_device_number () {
+	local md_num="$(grep ^md /proc/mdstat | \
+			sed -e 's/^md\(.*\) : active .*/\1/' | sort | tail -n1)"
+	if [ -z "$md_num" ]; then
+		md_num=0
+	else
+		md_num="$(($md_num + 1))"
+	fi
+	echo "$md_num"
+}
+
+md_lock_devices () {
+	local name dev
+	name="$1"
+	shift
+
+	db_subst partman-md/text/in_use DEVICE "$name"
+	db_metaget partman-md/text/in_use description
+	for dev; do
+		partman_lock_unit "$dev" "$RET"
+	done
+}


Reply to: